1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-19 12:02:24 +02:00

Restored ambient sounds functionality

This commit is contained in:
Ivan Savenko 2023-03-01 17:20:05 +02:00
parent cdcd5a29dd
commit b57a07b10f
18 changed files with 361 additions and 133 deletions

View File

@ -1000,10 +1000,6 @@ static void handleEvent(SDL_Event & ev)
case EUserEvent::FULLSCREEN_TOGGLED: case EUserEvent::FULLSCREEN_TOGGLED:
fullScreenChanged(); fullScreenChanged();
break; break;
case EUserEvent::INTERFACE_CHANGED:
if(LOCPLINT)
LOCPLINT->updateAmbientSounds(false);
break;
default: default:
logGlobal->error("Unknown user event. Code %d", ev.user.code); logGlobal->error("Unknown user event. Code %d", ev.user.code);
break; break;

View File

@ -10,6 +10,7 @@ set(client_SRCS
adventureMap/CList.cpp adventureMap/CList.cpp
adventureMap/CMinimap.cpp adventureMap/CMinimap.cpp
adventureMap/CResDataBar.cpp adventureMap/CResDataBar.cpp
adventureMap/MapAudioPlayer.cpp
battle/BattleActionsController.cpp battle/BattleActionsController.cpp
battle/BattleAnimationClasses.cpp battle/BattleAnimationClasses.cpp
@ -128,6 +129,7 @@ set(client_HEADERS
adventureMap/CList.h adventureMap/CList.h
adventureMap/CMinimap.h adventureMap/CMinimap.h
adventureMap/CResDataBar.h adventureMap/CResDataBar.h
adventureMap/MapAudioPlayer.h
battle/BattleActionsController.h battle/BattleActionsController.h
battle/BattleAnimationClasses.h battle/BattleAnimationClasses.h

View File

@ -75,7 +75,6 @@ CSoundHandler::CSoundHandler():
listener(settings.listen["general"]["sound"]), listener(settings.listen["general"]["sound"]),
ambientConfig(JsonNode(ResourceID("config/ambientSounds.json"))) ambientConfig(JsonNode(ResourceID("config/ambientSounds.json")))
{ {
allTilesSource = ambientConfig["allTilesSource"].Bool();
listener(std::bind(&CSoundHandler::onVolumeChange, this, _1)); listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
// Vectors for helper(s) // Vectors for helper(s)
@ -259,11 +258,6 @@ int CSoundHandler::ambientGetRange() const
return static_cast<int>(ambientConfig["range"].Integer()); return static_cast<int>(ambientConfig["range"].Integer());
} }
bool CSoundHandler::ambientCheckVisitable() const
{
return !allTilesSource;
}
void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg) void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
{ {
boost::mutex::scoped_lock guard(mutex); boost::mutex::scoped_lock guard(mutex);
@ -278,7 +272,9 @@ void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
} }
else else
{ {
CCS->soundh->setChannelVolume(pair.second, ambientDistToVolume(soundsArg[pair.first])); int volume = ambientDistToVolume(soundsArg[pair.first]);
CCS->soundh->setChannelVolume(pair.second, volume);
logGlobal->info("playing sound %s at %d", pair.first, volume);
} }
} }
for(auto soundId : stoppedSounds) for(auto soundId : stoppedSounds)
@ -289,8 +285,11 @@ void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
if(!vstd::contains(ambientChannels, pair.first)) if(!vstd::contains(ambientChannels, pair.first))
{ {
int channel = CCS->soundh->playSound(pair.first, -1); int channel = CCS->soundh->playSound(pair.first, -1);
CCS->soundh->setChannelVolume(channel, ambientDistToVolume(pair.second)); int volume = ambientDistToVolume(pair.second);
CCS->soundh->setChannelVolume(channel, volume);
CCS->soundh->ambientChannels.insert(std::make_pair(pair.first, channel)); CCS->soundh->ambientChannels.insert(std::make_pair(pair.first, channel));
logGlobal->info("playing sound %s at %d", pair.first, volume);
} }
} }
} }

View File

@ -53,7 +53,6 @@ private:
void ambientStopSound(std::string soundId); void ambientStopSound(std::string soundId);
const JsonNode ambientConfig; const JsonNode ambientConfig;
bool allTilesSource;
std::map<std::string, int> ambientChannels; std::map<std::string, int> ambientChannels;
public: public:
@ -75,7 +74,6 @@ public:
void soundFinishedCallback(int channel); void soundFinishedCallback(int channel);
int ambientGetRange() const; int ambientGetRange() const;
bool ambientCheckVisitable() const;
void ambientUpdateChannels(std::map<std::string, int> currentSounds); void ambientUpdateChannels(std::map<std::string, int> currentSounds);
void ambientStopAllChannels(); void ambientStopAllChannels();

View File

@ -215,7 +215,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
curAction = nullptr; curAction = nullptr;
playerID=Player; playerID=Player;
human=true; human=true;
currentSelection = nullptr;
battleInt = nullptr; battleInt = nullptr;
castleInt = nullptr; castleInt = nullptr;
makingTurn = false; makingTurn = false;
@ -233,9 +232,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
CPlayerInterface::~CPlayerInterface() CPlayerInterface::~CPlayerInterface()
{ {
if(CCS && CCS->soundh)
CCS->soundh->ambientStopAllChannels();
logGlobal->trace("\tHuman player interface for player %s being destructed", playerID.getStr()); logGlobal->trace("\tHuman player interface for player %s being destructed", playerID.getStr());
delete showingDialog; delete showingDialog;
delete cingconsole; delete cingconsole;
@ -341,10 +337,6 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
{ {
updateAmbientSounds(false);
//We may need to change music - select new track, music handler will change it if needed
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->getJsonKey(), true, false);
if(details.result == TryMoveHero::TELEPORTATION) if(details.result == TryMoveHero::TELEPORTATION)
{ {
if(paths.hasPath(hero)) if(paths.hasPath(hero))
@ -1542,17 +1534,6 @@ void CPlayerInterface::playerBlocked(int reason, bool start)
} }
} }
const CArmedInstance * CPlayerInterface::getSelection()
{
return currentSelection;
}
void CPlayerInterface::setSelection(const CArmedInstance * obj)
{
currentSelection = obj;
updateAmbientSounds(true);
}
void CPlayerInterface::update() void CPlayerInterface::update()
{ {
// Make sure that gamestate won't change when GUI objects may obtain its parts on event processing or drawing request // Make sure that gamestate won't change when GUI objects may obtain its parts on event processing or drawing request
@ -1877,7 +1858,6 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj)
void CPlayerInterface::requestReturningToMainMenu(bool won) void CPlayerInterface::requestReturningToMainMenu(bool won)
{ {
CCS->soundh->ambientStopAllChannels();
if(won && cb->getStartInfo()->campState) if(won && cb->getStartInfo()->campState)
CSH->startCampaignScenario(cb->getStartInfo()->campState); CSH->startCampaignScenario(cb->getStartInfo()->campState);
else else
@ -2226,41 +2206,3 @@ void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectP
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->openWorldView(objectPositions, showTerrain ); adventureInt->openWorldView(objectPositions, showTerrain );
} }
void CPlayerInterface::updateAmbientSounds(bool resetAll)
{
if(castleInt || battleInt || !makingTurn || !currentSelection)
{
CCS->soundh->ambientStopAllChannels();
return;
}
else if(!dynamic_cast<CAdvMapInt *>(GH.topInt().get()))
{
return;
}
if(resetAll)
CCS->soundh->ambientStopAllChannels();
std::map<std::string, int> currentSounds;
auto updateSounds = [&](std::string soundId, int distance) -> void
{
if(vstd::contains(currentSounds, soundId))
currentSounds[soundId] = std::max(currentSounds[soundId], distance);
else
currentSounds.insert(std::make_pair(soundId, distance));
};
int3 pos = currentSelection->getSightCenter();
std::unordered_set<int3, ShashInt3> tiles;
cb->getVisibleTilesInRange(tiles, pos, CCS->soundh->ambientGetRange(), int3::DIST_CHEBYSHEV);
for(int3 tile : tiles)
{
int dist = pos.dist(tile, int3::DIST_CHEBYSHEV);
// We want sound for every special terrain on tile and not just one on top
for(auto & soundName : CGI->mh->getAmbientSounds(tile))
updateSounds(soundName, dist);
}
CCS->soundh->ambientUpdateChannels(currentSounds);
}

View File

@ -92,8 +92,6 @@ public:
/// Central class for managing user interface logic /// Central class for managing user interface logic
class CPlayerInterface : public CGameInterface, public IUpdateable class CPlayerInterface : public CGameInterface, public IUpdateable
{ {
const CArmedInstance * currentSelection;
public: public:
HeroPathStorage paths; HeroPathStorage paths;
@ -263,9 +261,6 @@ public:
void requestReturningToMainMenu(bool won); void requestReturningToMainMenu(bool won);
void proposeLoadingGame(); void proposeLoadingGame();
// Ambient sounds
void updateAmbientSounds(bool resetAll);
///returns true if all events are processed internally ///returns true if all events are processed internally
bool capturedAllEvents(); bool capturedAllEvents();

View File

@ -17,6 +17,7 @@
#include "CResDataBar.h" #include "CResDataBar.h"
#include "CList.h" #include "CList.h"
#include "CInfoBar.h" #include "CInfoBar.h"
#include "MapAudioPlayer.h"
#include "../mapView/mapHandler.h" #include "../mapView/mapHandler.h"
#include "../mapView/MapView.h" #include "../mapView/MapView.h"
@ -87,6 +88,7 @@ CAdvMapInt::CAdvMapInt():
townList(new CTownList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD)), townList(new CTownList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD)),
infoBar(new CInfoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192))), infoBar(new CInfoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192))),
resdatabar(new CResDataBar), resdatabar(new CResDataBar),
mapAudio(new MapAudioPlayer()),
terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))), terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))),
state(NA), state(NA),
spellBeingCasted(nullptr), spellBeingCasted(nullptr),
@ -298,6 +300,16 @@ void CAdvMapInt::onMapViewMoved(const Rect & visibleArea, int mapLevel)
minimap->onMapViewMoved(visibleArea, mapLevel); minimap->onMapViewMoved(visibleArea, mapLevel);
} }
void CAdvMapInt::onAudioResumed()
{
mapAudio->onAudioResumed();
}
void CAdvMapInt::onAudioPaused()
{
mapAudio->onAudioPaused();
}
void CAdvMapInt::fshowQuestlog() void CAdvMapInt::fshowQuestlog()
{ {
LOCPLINT->showQuestLog(); LOCPLINT->showQuestLog();
@ -854,15 +866,8 @@ boost::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
void CAdvMapInt::select(const CArmedInstance *sel, bool centerView) void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
{ {
assert(sel); assert(sel);
LOCPLINT->setSelection(sel);
selection = sel; selection = sel;
if (LOCPLINT->battleInt == nullptr && LOCPLINT->makingTurn) mapAudio->onSelectionChanged(sel);
{
auto pos = sel->visitablePos();
auto tile = LOCPLINT->cb->getTile(pos);
if(tile)
CCS->musich->playMusicFromSet("terrain", tile->terType->getJsonKey(), true, false);
}
if(centerView) if(centerView)
centerOnObject(sel); centerOnObject(sel);
@ -974,6 +979,7 @@ void CAdvMapInt::initializeNewTurn()
{ {
heroList->update(); heroList->update();
townList->update(); townList->update();
mapAudio->onPlayerTurnStarted();
const CGHeroInstance * heroToSelect = nullptr; const CGHeroInstance * heroToSelect = nullptr;
@ -1021,7 +1027,7 @@ void CAdvMapInt::endingTurn()
LOCPLINT->makingTurn = false; LOCPLINT->makingTurn = false;
LOCPLINT->cb->endTurn(); LOCPLINT->cb->endTurn();
CCS->soundh->ambientStopAllChannels(); mapAudio->onPlayerTurnEnded();
} }
const CGObjectInstance* CAdvMapInt::getActiveObject(const int3 &mapPos) const CGObjectInstance* CAdvMapInt::getActiveObject(const int3 &mapPos)
@ -1388,7 +1394,7 @@ void CAdvMapInt::aiTurnStarted()
return; return;
adjustActiveness(true); adjustActiveness(true);
CCS->musich->playMusicFromSet("enemy-turn", true, false); mapAudio->onEnemyTurnStarted();
adventureInt->minimap->setAIRadar(true); adventureInt->minimap->setAIRadar(true);
adventureInt->infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer()); adventureInt->infoBar->startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->infoBar->showAll(screen);//force refresh on inactive object adventureInt->infoBar->showAll(screen);//force refresh on inactive object

View File

@ -39,6 +39,7 @@ class CHeroList;
class CTownList; class CTownList;
class CInfoBar; class CInfoBar;
class CMinimap; class CMinimap;
class MapAudioPlayer;
struct MapDrawingInfo; struct MapDrawingInfo;
@ -107,6 +108,8 @@ private:
std::shared_ptr<CAnimation> worldViewIcons;// images for world view overlay std::shared_ptr<CAnimation> worldViewIcons;// images for world view overlay
std::shared_ptr<MapAudioPlayer> mapAudio;
private: private:
//functions bound to buttons //functions bound to buttons
void fshowOverview(); void fshowOverview();
@ -163,6 +166,12 @@ public:
/// visibleArea describen now visible map section measured in tiles /// visibleArea describen now visible map section measured in tiles
void onMapViewMoved(const Rect & visibleArea, int mapLevel); void onMapViewMoved(const Rect & visibleArea, int mapLevel);
/// Called when map audio should be paused, e.g. on combat or town scren access
void onAudioPaused();
/// Called when map audio should be resume, opposite to onPaused
void onAudioResumed();
void select(const CArmedInstance *sel, bool centerView = true); void select(const CArmedInstance *sel, bool centerView = true);
void centerOnTile(int3 on); void centerOnTile(int3 on);
void centerOnObject(const CGObjectInstance *obj); void centerOnObject(const CGObjectInstance *obj);

View File

@ -11,12 +11,13 @@
#include "StdInc.h" #include "StdInc.h"
#include "CInGameConsole.h" #include "CInGameConsole.h"
#include "../render/Colors.h"
#include "../CGameInfo.h" #include "../CGameInfo.h"
#include "../CMusicHandler.h" #include "../CMusicHandler.h"
#include "../CPlayerInterface.h" #include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../ClientCommandManager.h" #include "../ClientCommandManager.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../gui/CGuiHandler.h"
#include "../render/Colors.h"
#include "../../CCallback.h" #include "../../CCallback.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
@ -234,7 +235,7 @@ void CInGameConsole::endEnteringText(bool processEnteredText)
clientCommandThread.detach(); clientCommandThread.detach();
} }
else else
LOCPLINT->cb->sendMessage(txt, LOCPLINT->getSelection()); LOCPLINT->cb->sendMessage(txt, adventureInt->curArmy());
} }
enteredText.clear(); enteredText.clear();

View File

@ -0,0 +1,247 @@
/*
* MapAudioPlayer.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "MapAudioPlayer.h"
#include "../mapView/mapHandler.h"
#include "../CPlayerInterface.h"
#include "../CGameInfo.h"
#include "../CCallback.h"
#include "../CMusicHandler.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/mapObjects/CArmedInstance.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/TerrainHandler.h"
bool MapAudioPlayer::hasOngoingAnimations()
{
return false;
}
void MapAudioPlayer::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
{
if (obj == currentSelection)
update();
}
void MapAudioPlayer::onAfterHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
{
if (obj == currentSelection)
update();
}
void MapAudioPlayer::onAfterHeroEmbark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
{
if (obj == currentSelection)
update();
}
void MapAudioPlayer::onAfterHeroDisembark(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
{
if (obj == currentSelection)
update();
}
void MapAudioPlayer::onObjectFadeIn(const CGObjectInstance * obj)
{
addObject(obj);
}
void MapAudioPlayer::onObjectFadeOut(const CGObjectInstance * obj)
{
removeObject(obj);
}
void MapAudioPlayer::onObjectInstantAdd(const CGObjectInstance * obj)
{
addObject(obj);
}
void MapAudioPlayer::onObjectInstantRemove(const CGObjectInstance * obj)
{
removeObject(obj);
}
void MapAudioPlayer::addObject(const CGObjectInstance * obj)
{
if (obj->isTile2Terrain())
{
// terrain overlay - all covering tiles act as sound source
for(int fx = 0; fx < obj->getWidth(); ++fx)
{
for(int fy = 0; fy < obj->getHeight(); ++fy)
{
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
if(LOCPLINT->cb->isInTheMap(currTile) && obj->coveringAt(currTile.x, currTile.y))
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);
}
}
return;
}
if (obj->isVisitable())
{
// visitable object - visitable tile acts as sound source
int3 currTile = obj->visitablePos();
if(LOCPLINT->cb->isInTheMap(currTile))
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);
return;
}
if (!obj->isVisitable())
{
// static object - blocking tiles act as sound source
auto tiles = obj->getBlockedOffsets();
for (const auto & tile : tiles)
{
int3 currTile = obj->pos + tile;
if(LOCPLINT->cb->isInTheMap(currTile))
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);
}
return;
}
}
void MapAudioPlayer::removeObject(const CGObjectInstance * obj)
{
for(int z = 0; z < LOCPLINT->cb->getMapSize().z; z++)
for(int x = 0; x < LOCPLINT->cb->getMapSize().x; x++)
for(int y = 0; y < LOCPLINT->cb->getMapSize().y; y++)
vstd::erase(objects[z][x][y], obj->id);
}
std::vector<std::string> MapAudioPlayer::getAmbientSounds(const int3 & tile)
{
std::vector<std::string> result;
for(auto & objectID : objects[tile.z][tile.x][tile.y])
{
const auto & object = CGI->mh->getMap()->objects[objectID.getNum()];
if(object->getAmbientSound())
result.push_back(object->getAmbientSound().get());
}
if(CGI->mh->getMap()->isCoastalTile(tile))
result.emplace_back("LOOPOCEA");
return result;
}
void MapAudioPlayer::updateAmbientSounds()
{
std::map<std::string, int> currentSounds;
auto updateSounds = [&](std::string soundId, int distance) -> void
{
if(vstd::contains(currentSounds, soundId))
currentSounds[soundId] = std::min(currentSounds[soundId], distance);
else
currentSounds.insert(std::make_pair(soundId, distance));
};
int3 pos = currentSelection->getSightCenter();
std::unordered_set<int3, ShashInt3> tiles;
LOCPLINT->cb->getVisibleTilesInRange(tiles, pos, CCS->soundh->ambientGetRange(), int3::DIST_CHEBYSHEV);
for(int3 tile : tiles)
{
int dist = pos.dist(tile, int3::DIST_CHEBYSHEV);
for(auto & soundName : getAmbientSounds(tile))
updateSounds(soundName, dist);
}
CCS->soundh->ambientUpdateChannels(currentSounds);
}
void MapAudioPlayer::updateMusic()
{
if (audioPlaying && playerMakingTurn && currentSelection)
{
const auto * terrain = LOCPLINT->cb->getTile(currentSelection->visitablePos())->terType;
CCS->musich->playMusicFromSet("terrain", terrain->getJsonKey(), true, false);
}
if (audioPlaying && enemyMakingTurn)
{
CCS->musich->playMusicFromSet("enemy-turn", true, false);
}
}
void MapAudioPlayer::update()
{
updateMusic();
if (audioPlaying && playerMakingTurn && currentSelection)
updateAmbientSounds();
}
MapAudioPlayer::MapAudioPlayer()
{
auto mapSize = LOCPLINT->cb->getMapSize();
objects.resize(boost::extents[mapSize.z][mapSize.x][mapSize.y]);
for(const auto & obj : CGI->mh->getMap()->objects)
addObject(obj);
}
MapAudioPlayer::~MapAudioPlayer()
{
CCS->soundh->ambientStopAllChannels();
CCS->musich->stopMusic(1000);
}
void MapAudioPlayer::onSelectionChanged(const CArmedInstance * newSelection)
{
currentSelection = newSelection;
update();
}
void MapAudioPlayer::onAudioPaused()
{
audioPlaying = false;
CCS->soundh->ambientStopAllChannels();
CCS->musich->stopMusic(1000);
}
void MapAudioPlayer::onAudioResumed()
{
audioPlaying = true;
update();
}
void MapAudioPlayer::onPlayerTurnStarted()
{
enemyMakingTurn = false;
playerMakingTurn = true;
update();
}
void MapAudioPlayer::onEnemyTurnStarted()
{
playerMakingTurn = false;
enemyMakingTurn = true;
update();
}
void MapAudioPlayer::onPlayerTurnEnded()
{
playerMakingTurn = false;
enemyMakingTurn = false;
CCS->soundh->ambientStopAllChannels();
CCS->musich->stopMusic(1000);
}

View File

@ -0,0 +1,71 @@
/*
* MapAudioPlayer.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../mapView/IMapRendererObserver.h"
VCMI_LIB_NAMESPACE_BEGIN
class ObjectInstanceID;
class CArmedInstance;
VCMI_LIB_NAMESPACE_END
class MapAudioPlayer : public IMapObjectObserver
{
using MapObjectsList = std::vector<ObjectInstanceID>;
boost::multi_array<MapObjectsList, 3> objects;
const CArmedInstance * currentSelection = nullptr;
bool playerMakingTurn = false;
bool enemyMakingTurn = false;
bool audioPlaying = true;
void addObject(const CGObjectInstance * obj);
void removeObject(const CGObjectInstance * obj);
std::vector<std::string> getAmbientSounds(const int3 & tile);
void updateAmbientSounds();
void updateMusic();
void update();
protected:
// IMapObjectObserver impl
bool hasOngoingAnimations() override;
void onObjectFadeIn(const CGObjectInstance * obj) override;
void onObjectFadeOut(const CGObjectInstance * obj) override;
void onObjectInstantAdd(const CGObjectInstance * obj) override;
void onObjectInstantRemove(const CGObjectInstance * obj) override;
void onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
void onAfterHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
void onAfterHeroEmbark(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
void onAfterHeroDisembark(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
public:
MapAudioPlayer();
~MapAudioPlayer();
/// Called whenever current adventure map selection changes
void onSelectionChanged(const CArmedInstance * newSelection);
/// Called when local player starts his turn
void onPlayerTurnStarted();
/// Called when AI or non-local player start his turn
void onEnemyTurnStarted();
/// Called when local player ends his turn
void onPlayerTurnEnded();
/// Called when map audio should be paused, e.g. on combat or town scren access
void onAudioPaused();
/// Called when map audio should be resume, opposite to onPaused
void onAudioResumed();
};

View File

@ -95,7 +95,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
effectsController.reset(new BattleEffectsController(*this)); effectsController.reset(new BattleEffectsController(*this));
obstacleController.reset(new BattleObstacleController(*this)); obstacleController.reset(new BattleObstacleController(*this));
CCS->musich->stopMusic(); adventureInt->onAudioPaused();
setAnimationCondition(EAnimationEvents::OPENING, true); setAnimationCondition(EAnimationEvents::OPENING, true);
GH.pushInt(windowObject); GH.pushInt(windowObject);
@ -144,12 +144,8 @@ BattleInterface::~BattleInterface()
CPlayerInterface::battleInt = nullptr; CPlayerInterface::battleInt = nullptr;
givenCommand.cond.notify_all(); //that two lines should make any stacksController->getActiveStack() waiting thread to finish givenCommand.cond.notify_all(); //that two lines should make any stacksController->getActiveStack() waiting thread to finish
if (adventureInt && adventureInt->curArmy()) if (adventureInt)
{ adventureInt->onAudioResumed();
//FIXME: this should be moved to adventureInt which should restore correct track based on selection/active player
const auto * terrain = LOCPLINT->cb->getTile(adventureInt->curArmy()->visitablePos())->terType;
CCS->musich->playMusicFromSet("terrain", terrain->getJsonKey(), true, false);
}
// may happen if user decided to close game while in battle // may happen if user decided to close game while in battle
if (getAnimationCondition(EAnimationEvents::ACTION) == true) if (getAnimationCondition(EAnimationEvents::ACTION) == true)

View File

@ -126,8 +126,6 @@ void CGuiHandler::popInt(std::shared_ptr<IShowActivatable> top)
if(!listInt.empty()) if(!listInt.empty())
listInt.front()->activate(); listInt.front()->activate();
totalRedraw(); totalRedraw();
pushUserEvent(EUserEvent::INTERFACE_CHANGED);
} }
void CGuiHandler::pushInt(std::shared_ptr<IShowActivatable> newInt) void CGuiHandler::pushInt(std::shared_ptr<IShowActivatable> newInt)
@ -145,8 +143,6 @@ void CGuiHandler::pushInt(std::shared_ptr<IShowActivatable> newInt)
newInt->activate(); newInt->activate();
objsToBlit.push_back(newInt); objsToBlit.push_back(newInt);
totalRedraw(); totalRedraw();
pushUserEvent(EUserEvent::INTERFACE_CHANGED);
} }
void CGuiHandler::popInts(int howMany) void CGuiHandler::popInts(int howMany)
@ -168,8 +164,6 @@ void CGuiHandler::popInts(int howMany)
totalRedraw(); totalRedraw();
} }
fakeMouseMove(); fakeMouseMove();
pushUserEvent(EUserEvent::INTERFACE_CHANGED);
} }
std::shared_ptr<IShowActivatable> CGuiHandler::topInt() std::shared_ptr<IShowActivatable> CGuiHandler::topInt()

View File

@ -42,7 +42,6 @@ enum class EUserEvent
FULLSCREEN_TOGGLED, FULLSCREEN_TOGGLED,
CAMPAIGN_START_SCENARIO, CAMPAIGN_START_SCENARIO,
FORCE_QUIT, //quit client without question FORCE_QUIT, //quit client without question
INTERFACE_CHANGED
}; };
// A fps manager which holds game updates at a constant rate // A fps manager which holds game updates at a constant rate

View File

@ -136,21 +136,6 @@ bool CMapHandler::isInMap( const int3 & tile)
return map->isInTheMap(tile); return map->isInTheMap(tile);
} }
std::vector<std::string> CMapHandler::getAmbientSounds(const int3 & tile)
{
std::vector<std::string> result;
//for(auto & ttObj : ttiles[tile.z][tile.x][tile.y].objects)
//{
// if(ttObj.ambientSound)
// result.push_back(ttObj.ambientSound.get());
//}
if(map->isCoastalTile(tile))
result.emplace_back("LOOPOCEA");
return result;
}
void CMapHandler::onObjectFadeIn(const CGObjectInstance * obj) void CMapHandler::onObjectFadeIn(const CGObjectInstance * obj)
{ {
for (auto * observer : observers) for (auto * observer : observers)

View File

@ -28,17 +28,10 @@ VCMI_LIB_NAMESPACE_BEGIN
class CGObjectInstance; class CGObjectInstance;
class CGHeroInstance; class CGHeroInstance;
class CGBoat;
class CMap; class CMap;
struct TerrainTile;
class PlayerColor;
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
struct SDL_Surface;
class CAnimation;
class IImage;
class CMapHandler;
class IMapObjectObserver; class IMapObjectObserver;
class CMapHandler class CMapHandler
@ -74,9 +67,6 @@ public:
/// returns string description for terrain interaction /// returns string description for terrain interaction
std::string getTerrainDescr(const int3 & pos, bool rightClick) const; std::string getTerrainDescr(const int3 & pos, bool rightClick) const;
/// returns list of ambient sounds for specified tile
std::vector<std::string> getAmbientSounds(const int3 & tile);
/// determines if the map is ready to handle new hero movement (not available during fading animations) /// determines if the map is ready to handle new hero movement (not available during fading animations)
bool hasOngoingAnimations(); bool hasOngoingAnimations();

View File

@ -1188,11 +1188,13 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
townlist->onSelect = std::bind(&CCastleInterface::townChange, this); townlist->onSelect = std::bind(&CCastleInterface::townChange, this);
recreateIcons(); recreateIcons();
adventureInt->onAudioPaused();
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false); CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false);
} }
CCastleInterface::~CCastleInterface() CCastleInterface::~CCastleInterface()
{ {
adventureInt->onAudioResumed();
if(LOCPLINT->castleInt == this) if(LOCPLINT->castleInt == this)
LOCPLINT->castleInt = nullptr; LOCPLINT->castleInt = nullptr;
} }

View File

@ -1,8 +1,4 @@
{ {
// By default visitable objects only have ambient sound source on visitable tile
// Static objects and special terrains that have ambient sound have source on all tiles
// If set to true then all tiles will become source for visitable objects
"allTilesSource": false,
// By default SDL2_Mixer allocate 8 channels, but more sounds require more channels // By default SDL2_Mixer allocate 8 channels, but more sounds require more channels
"allocateChannels" : 16, "allocateChannels" : 16,
// Maximal ambient sounds volume must be about 20% of global effects volume // Maximal ambient sounds volume must be about 20% of global effects volume