Use ResourcePath for audio files

This commit is contained in:
Ivan Savenko
2023-09-04 18:22:34 +03:00
parent 97b7d44c88
commit 8dfdfffd87
59 changed files with 195 additions and 192 deletions
+1 -1
View File
@@ -387,7 +387,7 @@ void AIGateway::heroCreated(const CGHeroInstance * h)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void AIGateway::advmapSpellCast(const CGHeroInstance * caster, int spellID) void AIGateway::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
{ {
LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID); LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
+1 -1
View File
@@ -152,7 +152,7 @@ public:
void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override; void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
void playerBonusChanged(const Bonus & bonus, bool gain) override; void playerBonusChanged(const Bonus & bonus, bool gain) override;
void heroCreated(const CGHeroInstance *) override; void heroCreated(const CGHeroInstance *) override;
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override;
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override; void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
void requestRealized(PackageApplied * pa) override; void requestRealized(PackageApplied * pa) override;
void receivedResource() override; void receivedResource() override;
+1 -1
View File
@@ -475,7 +475,7 @@ void VCAI::heroCreated(const CGHeroInstance * h)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID) void VCAI::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
{ {
LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID); LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
+1 -1
View File
@@ -185,7 +185,7 @@ public:
void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override; void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
void playerBonusChanged(const Bonus & bonus, bool gain) override; void playerBonusChanged(const Bonus & bonus, bool gain) override;
void heroCreated(const CGHeroInstance *) override; void heroCreated(const CGHeroInstance *) override;
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override;
void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override; void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
void requestRealized(PackageApplied * pa) override; void requestRealized(PackageApplied * pa) override;
void receivedResource() override; void receivedResource() override;
+31 -31
View File
@@ -119,25 +119,25 @@ void CSoundHandler::release()
} }
// Allocate an SDL chunk and cache it. // Allocate an SDL chunk and cache it.
Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound, bool cache) Mix_Chunk *CSoundHandler::GetSoundChunk(const AudioPath & sound, bool cache)
{ {
try try
{ {
if (cache && soundChunks.find(sound) != soundChunks.end()) if (cache && soundChunks.find(sound) != soundChunks.end())
return soundChunks[sound].first; return soundChunks[sound].first;
auto data = CResourceHandler::get()->load(ResourcePath(std::string("SOUNDS/") + sound, EResType::SOUND))->readAll(); auto data = CResourceHandler::get()->load(sound.addPrefix("SOUNDS/"))->readAll();
SDL_RWops *ops = SDL_RWFromMem(data.first.get(), (int)data.second); SDL_RWops *ops = SDL_RWFromMem(data.first.get(), (int)data.second);
Mix_Chunk *chunk = Mix_LoadWAV_RW(ops, 1); // will free ops Mix_Chunk *chunk = Mix_LoadWAV_RW(ops, 1); // will free ops
if (cache) if (cache)
soundChunks.insert(std::pair<std::string, CachedChunk>(sound, std::make_pair (chunk, std::move (data.first)))); soundChunks.insert({sound, std::make_pair (chunk, std::move (data.first))});
return chunk; return chunk;
} }
catch(std::exception &e) catch(std::exception &e)
{ {
logGlobal->warn("Cannot get sound %s chunk: %s", sound, e.what()); logGlobal->warn("Cannot get sound %s chunk: %s", sound.getOriginalName(), e.what());
return nullptr; return nullptr;
} }
} }
@@ -153,7 +153,7 @@ int CSoundHandler::ambientDistToVolume(int distance) const
return volume * (int)ambientConfig["volume"].Integer() / 100; return volume * (int)ambientConfig["volume"].Integer() / 100;
} }
void CSoundHandler::ambientStopSound(std::string soundId) void CSoundHandler::ambientStopSound(const AudioPath & soundId)
{ {
stopSound(ambientChannels[soundId]); stopSound(ambientChannels[soundId]);
setChannelVolume(ambientChannels[soundId], volume); setChannelVolume(ambientChannels[soundId], volume);
@@ -163,13 +163,13 @@ void CSoundHandler::ambientStopSound(std::string soundId)
int CSoundHandler::playSound(soundBase::soundID soundID, int repeats) int CSoundHandler::playSound(soundBase::soundID soundID, int repeats)
{ {
assert(soundID < soundBase::sound_after_last); assert(soundID < soundBase::sound_after_last);
auto sound = sounds[soundID]; auto sound = AudioPath::builtin(sounds[soundID]);
logGlobal->trace("Attempt to play sound %d with file name %s with cache", soundID, sound); logGlobal->trace("Attempt to play sound %d with file name %s with cache", soundID, sound.getOriginalName());
return playSound(sound, repeats, true); return playSound(sound, repeats, true);
} }
int CSoundHandler::playSound(std::string sound, int repeats, bool cache) int CSoundHandler::playSound(const AudioPath & sound, int repeats, bool cache)
{ {
if (!initialized || sound.empty()) if (!initialized || sound.empty())
return -1; return -1;
@@ -182,7 +182,7 @@ int CSoundHandler::playSound(std::string sound, int repeats, bool cache)
channel = Mix_PlayChannel(-1, chunk, repeats); channel = Mix_PlayChannel(-1, chunk, repeats);
if (channel == -1) if (channel == -1)
{ {
logGlobal->error("Unable to play sound file %s , error %s", sound, Mix_GetError()); logGlobal->error("Unable to play sound file %s , error %s", sound.getOriginalName(), Mix_GetError());
if (!cache) if (!cache)
Mix_FreeChunk(chunk); Mix_FreeChunk(chunk);
} }
@@ -290,14 +290,14 @@ int CSoundHandler::ambientGetRange() const
return static_cast<int>(ambientConfig["range"].Integer()); return static_cast<int>(ambientConfig["range"].Integer());
} }
void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg) void CSoundHandler::ambientUpdateChannels(std::map<AudioPath, int> soundsArg)
{ {
boost::mutex::scoped_lock guard(mutex); boost::mutex::scoped_lock guard(mutex);
std::vector<std::string> stoppedSounds; std::vector<AudioPath> stoppedSounds;
for(auto & pair : ambientChannels) for(auto & pair : ambientChannels)
{ {
const std::string & soundId = pair.first; const auto & soundId = pair.first;
const int channel = pair.second; const int channel = pair.second;
if(!vstd::contains(soundsArg, soundId)) if(!vstd::contains(soundsArg, soundId))
@@ -320,7 +320,7 @@ void CSoundHandler::ambientUpdateChannels(std::map<std::string, int> soundsArg)
for(auto & pair : soundsArg) for(auto & pair : soundsArg)
{ {
const std::string & soundId = pair.first; const auto & soundId = pair.first;
const int distance = pair.second; const int distance = pair.second;
if(!vstd::contains(ambientChannels, soundId)) if(!vstd::contains(ambientChannels, soundId))
@@ -372,9 +372,9 @@ CMusicHandler::CMusicHandler():
for(const ResourcePath & file : mp3files) for(const ResourcePath & file : mp3files)
{ {
if(boost::algorithm::istarts_with(file.getName(), "MUSIC/Combat")) if(boost::algorithm::istarts_with(file.getName(), "MUSIC/Combat"))
addEntryToSet("battle", file.getName()); addEntryToSet("battle", AudioPath::fromResource(file));
else if(boost::algorithm::istarts_with(file.getName(), "MUSIC/AITheme")) else if(boost::algorithm::istarts_with(file.getName(), "MUSIC/AITheme"))
addEntryToSet("enemy-turn", file.getName()); addEntryToSet("enemy-turn", AudioPath::fromResource(file));
} }
} }
@@ -383,11 +383,11 @@ void CMusicHandler::loadTerrainMusicThemes()
{ {
for (const auto & terrain : CGI->terrainTypeHandler->objects) for (const auto & terrain : CGI->terrainTypeHandler->objects)
{ {
addEntryToSet("terrain_" + terrain->getJsonKey(), "Music/" + terrain->musicFilename); addEntryToSet("terrain_" + terrain->getJsonKey(), terrain->musicFilename);
} }
} }
void CMusicHandler::addEntryToSet(const std::string & set, const std::string & musicURI) void CMusicHandler::addEntryToSet(const std::string & set, const AudioPath & musicURI)
{ {
musicsSet[set].push_back(musicURI); musicsSet[set].push_back(musicURI);
} }
@@ -421,7 +421,7 @@ void CMusicHandler::release()
CAudioBase::release(); CAudioBase::release();
} }
void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart) void CMusicHandler::playMusic(const AudioPath & musicURI, bool loop, bool fromStart)
{ {
boost::mutex::scoped_lock guard(mutex); boost::mutex::scoped_lock guard(mutex);
@@ -451,7 +451,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bo
return; return;
// in this mode - play random track from set // in this mode - play random track from set
queueNext(this, whichSet, "", loop, fromStart); queueNext(this, whichSet, AudioPath(), loop, fromStart);
} }
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued) void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
@@ -468,7 +468,7 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
} }
} }
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart) void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const AudioPath & musicURI, bool looped, bool fromStart)
{ {
queueNext(std::make_unique<MusicEntry>(owner, setName, musicURI, looped, fromStart)); queueNext(std::make_unique<MusicEntry>(owner, setName, musicURI, looped, fromStart));
} }
@@ -523,7 +523,7 @@ void CMusicHandler::musicFinishedCallback()
}); });
} }
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart): MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, const AudioPath & musicURI, bool looped, bool fromStart):
owner(owner), owner(owner),
music(nullptr), music(nullptr),
playing(false), playing(false),
@@ -552,16 +552,16 @@ MusicEntry::~MusicEntry()
Mix_HaltMusic(); Mix_HaltMusic();
} }
logGlobal->trace("Del-ing music file %s", currentName); logGlobal->trace("Del-ing music file %s", currentName.getOriginalName());
if (music) if (music)
Mix_FreeMusic(music); Mix_FreeMusic(music);
} }
void MusicEntry::load(std::string musicURI) void MusicEntry::load(const AudioPath & musicURI)
{ {
if (music) if (music)
{ {
logGlobal->trace("Del-ing music file %s", currentName); logGlobal->trace("Del-ing music file %s", currentName.getOriginalName());
Mix_FreeMusic(music); Mix_FreeMusic(music);
music = nullptr; music = nullptr;
} }
@@ -569,22 +569,22 @@ void MusicEntry::load(std::string musicURI)
currentName = musicURI; currentName = musicURI;
music = nullptr; music = nullptr;
logGlobal->trace("Loading music file %s", musicURI); logGlobal->trace("Loading music file %s", musicURI.getOriginalName());
try try
{ {
auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourcePath(std::move(musicURI), EResType::SOUND))); auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(musicURI));
music = Mix_LoadMUS_RW(musicFile, SDL_TRUE); music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
} }
catch(std::exception &e) catch(std::exception &e)
{ {
logGlobal->error("Failed to load music. setName=%s\tmusicURI=%s", setName, musicURI); logGlobal->error("Failed to load music. setName=%s\tmusicURI=%s", setName, musicURI.getOriginalName());
logGlobal->error("Exception: %s", e.what()); logGlobal->error("Exception: %s", e.what());
} }
if(!music) if(!music)
{ {
logGlobal->warn("Warning: Cannot open %s: %s", currentName, Mix_GetError()); logGlobal->warn("Warning: Cannot open %s: %s", currentName.getOriginalName(), Mix_GetError());
return; return;
} }
} }
@@ -601,7 +601,7 @@ bool MusicEntry::play()
load(*iter); load(*iter);
} }
logGlobal->trace("Playing music file %s", currentName); logGlobal->trace("Playing music file %s", currentName.getOriginalName());
if (!fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0) if (!fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0)
{ {
@@ -646,7 +646,7 @@ bool MusicEntry::stop(int fade_ms)
assert(startTime != uint32_t(-1)); assert(startTime != uint32_t(-1));
float playDuration = (endTime - startTime + startPosition) / 1000.f; float playDuration = (endTime - startTime + startPosition) / 1000.f;
owner->trackPositions[currentName] = playDuration; owner->trackPositions[currentName] = playDuration;
logGlobal->trace("Stopping music file %s at %f", currentName, playDuration); logGlobal->trace("Stopping music file %s at %f", currentName.getOriginalName(), playDuration);
Mix_FadeOutMusic(fade_ms); Mix_FadeOutMusic(fade_ms);
return true; return true;
@@ -664,7 +664,7 @@ bool MusicEntry::isSet(std::string set)
return !setName.empty() && set == setName; return !setName.empty() && set == setName;
} }
bool MusicEntry::isTrack(std::string track) bool MusicEntry::isTrack(const AudioPath & track)
{ {
return setName.empty() && track == currentName; return setName.empty() && track == currentName;
} }
+15 -19
View File
@@ -35,15 +35,14 @@ public:
class CSoundHandler: public CAudioBase class CSoundHandler: public CAudioBase
{ {
private: private:
//soundBase::soundID getSoundID(const std::string &fileName);
//update volume on configuration change //update volume on configuration change
SettingsListener listener; SettingsListener listener;
void onVolumeChange(const JsonNode &volumeNode); void onVolumeChange(const JsonNode &volumeNode);
using CachedChunk = std::pair<Mix_Chunk *, std::unique_ptr<ui8[]>>; using CachedChunk = std::pair<Mix_Chunk *, std::unique_ptr<ui8[]>>;
std::map<std::string, CachedChunk> soundChunks; std::map<AudioPath, CachedChunk> soundChunks;
Mix_Chunk *GetSoundChunk(std::string &sound, bool cache); Mix_Chunk *GetSoundChunk(const AudioPath & sound, bool cache);
/// have entry for every currently active channel /// have entry for every currently active channel
/// vector will be empty if callback was not set /// vector will be empty if callback was not set
@@ -54,12 +53,12 @@ private:
boost::mutex mutexCallbacks; boost::mutex mutexCallbacks;
int ambientDistToVolume(int distance) const; int ambientDistToVolume(int distance) const;
void ambientStopSound(std::string soundId); void ambientStopSound(const AudioPath & soundId);
void updateChannelVolume(int channel); void updateChannelVolume(int channel);
const JsonNode ambientConfig; const JsonNode ambientConfig;
std::map<std::string, int> ambientChannels; std::map<AudioPath, int> ambientChannels;
std::map<int, int> channelVolumes; std::map<int, int> channelVolumes;
void initCallback(int channel, const std::function<void()> & function); void initCallback(int channel, const std::function<void()> & function);
@@ -76,7 +75,7 @@ public:
// Sounds // Sounds
int playSound(soundBase::soundID soundID, int repeats=0); int playSound(soundBase::soundID soundID, int repeats=0);
int playSound(std::string sound, int repeats=0, bool cache=false); int playSound(const AudioPath & sound, int repeats=0, bool cache=false);
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec); int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
void stopSound(int handler); void stopSound(int handler);
@@ -84,16 +83,13 @@ public:
void soundFinishedCallback(int channel); void soundFinishedCallback(int channel);
int ambientGetRange() const; int ambientGetRange() const;
void ambientUpdateChannels(std::map<std::string, int> currentSounds); void ambientUpdateChannels(std::map<AudioPath, int> currentSounds);
void ambientStopAllChannels(); void ambientStopAllChannels();
// Sets // Sets
std::vector<soundBase::soundID> battleIntroSounds; std::vector<soundBase::soundID> battleIntroSounds;
}; };
// Helper //now it looks somewhat useless
#define battle_sound(creature,what_sound) creature->sounds.what_sound
class CMusicHandler; class CMusicHandler;
//Class for handling one music file //Class for handling one music file
@@ -109,16 +105,16 @@ class MusicEntry
uint32_t startPosition; uint32_t startPosition;
//if not null - set from which music will be randomly selected //if not null - set from which music will be randomly selected
std::string setName; std::string setName;
std::string currentName; AudioPath currentName;
void load(std::string musicURI); void load(const AudioPath & musicURI);
public: public:
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart); MusicEntry(CMusicHandler *owner, std::string setName, const AudioPath & musicURI, bool looped, bool fromStart);
~MusicEntry(); ~MusicEntry();
bool isSet(std::string setName); bool isSet(std::string setName);
bool isTrack(std::string trackName); bool isTrack(const AudioPath & trackName);
bool isPlaying(); bool isPlaying();
bool play(); bool play();
@@ -135,20 +131,20 @@ private:
std::unique_ptr<MusicEntry> current; std::unique_ptr<MusicEntry> current;
std::unique_ptr<MusicEntry> next; std::unique_ptr<MusicEntry> next;
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart); void queueNext(CMusicHandler *owner, const std::string & setName, const AudioPath & musicURI, bool looped, bool fromStart);
void queueNext(std::unique_ptr<MusicEntry> queued); void queueNext(std::unique_ptr<MusicEntry> queued);
void musicFinishedCallback(); void musicFinishedCallback();
/// map <set name> -> <list of URI's to tracks belonging to the said set> /// map <set name> -> <list of URI's to tracks belonging to the said set>
std::map<std::string, std::vector<std::string>> musicsSet; std::map<std::string, std::vector<AudioPath>> musicsSet;
/// stored position, in seconds at which music player should resume playing this track /// stored position, in seconds at which music player should resume playing this track
std::map<std::string, float> trackPositions; std::map<AudioPath, float> trackPositions;
public: public:
CMusicHandler(); CMusicHandler();
/// add entry with URI musicURI in set. Track will have ID musicID /// add entry with URI musicURI in set. Track will have ID musicID
void addEntryToSet(const std::string & set, const std::string & musicURI); void addEntryToSet(const std::string & set, const AudioPath & musicURI);
void init() override; void init() override;
void loadTerrainMusicThemes(); void loadTerrainMusicThemes();
@@ -156,7 +152,7 @@ public:
void setVolume(ui32 percent) override; void setVolume(ui32 percent) override;
/// play track by URI, if loop = true music will be looped /// play track by URI, if loop = true music will be looped
void playMusic(const std::string & musicURI, bool loop, bool fromStart); void playMusic(const AudioPath & musicURI, bool loop, bool fromStart);
/// play random track from this set /// play random track from this set
void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart); void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart);
/// play random track from set (musicSet, entryID) /// play random track from set (musicSet, entryID)
+9 -10
View File
@@ -1657,7 +1657,7 @@ void CPlayerInterface::viewWorldMap()
adventureInt->openWorldView(); adventureInt->openWorldView();
} }
void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellID) void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, SpellID spellID)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
@@ -1667,8 +1667,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK) if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
localState->erasePath(caster); localState->erasePath(caster);
const spells::Spell * spell = CGI->spells()->getByIndex(spellID); auto castSoundPath = spellID.toSpell()->getCastSound();
auto castSoundPath = spell->getCastSound();
if(!castSoundPath.empty()) if(!castSoundPath.empty())
CCS->soundh->playSound(castSoundPath); CCS->soundh->playSound(castSoundPath);
} }
@@ -1992,22 +1991,22 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
elem.coord = h->convertFromVisitablePos(elem.coord); elem.coord = h->convertFromVisitablePos(elem.coord);
int soundChannel = -1; int soundChannel = -1;
std::string soundName; AudioPath soundName;
auto getMovementSoundFor = [&](const CGHeroInstance * hero, int3 posPrev, int3 posNext, EPathNodeAction moveType) -> std::string auto getMovementSoundFor = [&](const CGHeroInstance * hero, int3 posPrev, int3 posNext, EPathNodeAction moveType) -> AudioPath
{ {
if (moveType == EPathNodeAction::TELEPORT_BATTLE || moveType == EPathNodeAction::TELEPORT_BLOCKING_VISIT || moveType == EPathNodeAction::TELEPORT_NORMAL) if (moveType == EPathNodeAction::TELEPORT_BATTLE || moveType == EPathNodeAction::TELEPORT_BLOCKING_VISIT || moveType == EPathNodeAction::TELEPORT_NORMAL)
return ""; return {};
if (moveType == EPathNodeAction::EMBARK || moveType == EPathNodeAction::DISEMBARK) if (moveType == EPathNodeAction::EMBARK || moveType == EPathNodeAction::DISEMBARK)
return ""; return {};
if (moveType == EPathNodeAction::BLOCKING_VISIT) if (moveType == EPathNodeAction::BLOCKING_VISIT)
return ""; return {};
// flying movement sound // flying movement sound
if (hero->hasBonusOfType(BonusType::FLYING_MOVEMENT)) if (hero->hasBonusOfType(BonusType::FLYING_MOVEMENT))
return "HORSE10.wav"; return AudioPath::builtin("HORSE10.wav");
auto prevTile = cb->getTile(h->convertToVisitablePos(posPrev)); auto prevTile = cb->getTile(h->convertToVisitablePos(posPrev));
auto nextTile = cb->getTile(h->convertToVisitablePos(posNext)); auto nextTile = cb->getTile(h->convertToVisitablePos(posNext));
@@ -2073,7 +2072,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
{ {
// Start a new sound for the hero movement or let the existing one carry on. // Start a new sound for the hero movement or let the existing one carry on.
std::string newSoundName = getMovementSoundFor(h, prevCoord, nextCoord, path.nodes[i-1].action); AudioPath newSoundName = getMovementSoundFor(h, prevCoord, nextCoord, path.nodes[i-1].action);
if(newSoundName != soundName) if(newSoundName != soundName)
{ {
+1 -1
View File
@@ -128,7 +128,7 @@ protected: // Call-ins from server, should not be called directly, but only via
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override; void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override; void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override; void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; //called when a hero casts a spell void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell
void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war
void tileRevealed(const std::unordered_set<int3> &pos) override; //called when fog of war disappears from given tiles void tileRevealed(const std::unordered_set<int3> &pos) override; //called when fog of war disappears from given tiles
void newObject(const CGObjectInstance * obj) override; void newObject(const CGObjectInstance * obj) override;
+1 -1
View File
@@ -105,7 +105,7 @@ void CInGameConsole::print(const std::string & txt)
} }
GH.windows().totalRedraw(); // FIXME: ingame console has no parent widget set GH.windows().totalRedraw(); // FIXME: ingame console has no parent widget set
CCS->soundh->playSound("CHAT"); CCS->soundh->playSound(AudioPath::builtin("CHAT"));
} }
bool CInGameConsole::captureThisKey(EShortcut key) bool CInGameConsole::captureThisKey(EShortcut key)
+4 -4
View File
@@ -123,9 +123,9 @@ void MapAudioPlayer::removeObject(const CGObjectInstance * obj)
vstd::erase(objects[z][x][y], obj->id); vstd::erase(objects[z][x][y], obj->id);
} }
std::vector<std::string> MapAudioPlayer::getAmbientSounds(const int3 & tile) std::vector<AudioPath> MapAudioPlayer::getAmbientSounds(const int3 & tile)
{ {
std::vector<std::string> result; std::vector<AudioPath> result;
for(auto & objectID : objects[tile.z][tile.x][tile.y]) for(auto & objectID : objects[tile.z][tile.x][tile.y])
{ {
@@ -147,8 +147,8 @@ std::vector<std::string> MapAudioPlayer::getAmbientSounds(const int3 & tile)
void MapAudioPlayer::updateAmbientSounds() void MapAudioPlayer::updateAmbientSounds()
{ {
std::map<std::string, int> currentSounds; std::map<AudioPath, int> currentSounds;
auto updateSounds = [&](const std::string& soundId, int distance) -> void auto updateSounds = [&](const AudioPath& soundId, int distance) -> void
{ {
if(vstd::contains(currentSounds, soundId)) if(vstd::contains(currentSounds, soundId))
currentSounds[soundId] = std::min(currentSounds[soundId], distance); currentSounds[soundId] = std::min(currentSounds[soundId], distance);
+2 -1
View File
@@ -10,6 +10,7 @@
#pragma once #pragma once
#include "../mapView/IMapRendererObserver.h" #include "../mapView/IMapRendererObserver.h"
#include "../../lib/filesystem/ResourcePath.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class ObjectInstanceID; class ObjectInstanceID;
@@ -29,7 +30,7 @@ class MapAudioPlayer : public IMapObjectObserver
void addObject(const CGObjectInstance * obj); void addObject(const CGObjectInstance * obj);
void removeObject(const CGObjectInstance * obj); void removeObject(const CGObjectInstance * obj);
std::vector<std::string> getAmbientSounds(const int3 & tile); std::vector<AudioPath> getAmbientSounds(const int3 & tile);
void updateAmbientSounds(); void updateAmbientSounds();
void updateMusic(); void updateMusic();
void update(); void update();
+1 -1
View File
@@ -77,7 +77,7 @@ void TurnTimerWidget::setTime(PlayerColor player, int time)
&& newTime != turnTime && newTime != turnTime
&& notifications.count(newTime)) && notifications.count(newTime))
{ {
CCS->soundh->playSound(variables["notificationSound"].String()); CCS->soundh->playSound(AudioPath::fromJson(variables["notificationSound"]));
} }
turnTime = newTime; turnTime = newTime;
+10 -10
View File
@@ -114,7 +114,7 @@ void StackActionAnimation::setGroup( ECreatureAnimType group )
currGroup = group; currGroup = group;
} }
void StackActionAnimation::setSound( std::string sound ) void StackActionAnimation::setSound( const AudioPath & sound )
{ {
this->sound = sound; this->sound = sound;
} }
@@ -179,7 +179,7 @@ HittedAnimation::HittedAnimation(BattleInterface & owner, const CStack * stack)
: StackActionAnimation(owner, stack) : StackActionAnimation(owner, stack)
{ {
setGroup(ECreatureAnimType::HITTED); setGroup(ECreatureAnimType::HITTED);
setSound(battle_sound(stack->unitType(), wince)); setSound(stack->unitType()->sounds.wince);
logAnim->debug("Created HittedAnimation for %s", stack->getName()); logAnim->debug("Created HittedAnimation for %s", stack->getName());
} }
@@ -187,14 +187,14 @@ DefenceAnimation::DefenceAnimation(BattleInterface & owner, const CStack * stack
: StackActionAnimation(owner, stack) : StackActionAnimation(owner, stack)
{ {
setGroup(ECreatureAnimType::DEFENCE); setGroup(ECreatureAnimType::DEFENCE);
setSound(battle_sound(stack->unitType(), defend)); setSound(stack->unitType()->sounds.defend);
logAnim->debug("Created DefenceAnimation for %s", stack->getName()); logAnim->debug("Created DefenceAnimation for %s", stack->getName());
} }
DeathAnimation::DeathAnimation(BattleInterface & owner, const CStack * stack, bool ranged): DeathAnimation::DeathAnimation(BattleInterface & owner, const CStack * stack, bool ranged):
StackActionAnimation(owner, stack) StackActionAnimation(owner, stack)
{ {
setSound(battle_sound(stack->unitType(), killed)); setSound(stack->unitType()->sounds.killed);
if(ranged && myAnim->framesInGroup(ECreatureAnimType::DEATH_RANGED) > 0) if(ranged && myAnim->framesInGroup(ECreatureAnimType::DEATH_RANGED) > 0)
setGroup(ECreatureAnimType::DEATH_RANGED); setGroup(ECreatureAnimType::DEATH_RANGED);
@@ -315,7 +315,7 @@ MeleeAttackAnimation::MeleeAttackAnimation(BattleInterface & owner, const CStack
: AttackAnimation(owner, attacker, _dest, _attacked) : AttackAnimation(owner, attacker, _dest, _attacked)
{ {
logAnim->debug("Created MeleeAttackAnimation for %s", attacker->getName()); logAnim->debug("Created MeleeAttackAnimation for %s", attacker->getName());
setSound(battle_sound(getCreature(), attack)); setSound(getCreature()->sounds.attack);
setGroup(selectGroup(multiAttack)); setGroup(selectGroup(multiAttack));
} }
@@ -356,7 +356,7 @@ bool MovementAnimation::init()
if (moveSoundHander == -1) if (moveSoundHander == -1)
{ {
moveSoundHander = CCS->soundh->playSound(battle_sound(stack->unitType(), move), -1); moveSoundHander = CCS->soundh->playSound(stack->unitType()->sounds.move, -1);
} }
Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack); Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
@@ -453,7 +453,7 @@ bool MovementEndAnimation::init()
logAnim->debug("CMovementEndAnimation::init: stack %s", stack->getName()); logAnim->debug("CMovementEndAnimation::init: stack %s", stack->getName());
myAnim->pos.moveTo(owner.stacksController->getStackPositionAtHex(nextHex, stack)); myAnim->pos.moveTo(owner.stacksController->getStackPositionAtHex(nextHex, stack));
CCS->soundh->playSound(battle_sound(stack->unitType(), endMoving)); CCS->soundh->playSound(stack->unitType()->sounds.endMoving);
if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_END)) if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_END))
{ {
@@ -494,7 +494,7 @@ bool MovementStartAnimation::init()
} }
logAnim->debug("CMovementStartAnimation::init: stack %s", stack->getName()); logAnim->debug("CMovementStartAnimation::init: stack %s", stack->getName());
CCS->soundh->playSound(battle_sound(stack->unitType(), startMoving)); CCS->soundh->playSound(stack->unitType()->sounds.startMoving);
if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_START)) if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_START))
{ {
@@ -632,7 +632,7 @@ RangedAttackAnimation::RangedAttackAnimation(BattleInterface & owner_, const CSt
: AttackAnimation(owner_, attacker, dest_, defender), : AttackAnimation(owner_, attacker, dest_, defender),
projectileEmitted(false) projectileEmitted(false)
{ {
setSound(battle_sound(getCreature(), shoot)); setSound(getCreature()->sounds.shoot);
} }
bool RangedAttackAnimation::init() bool RangedAttackAnimation::init()
@@ -806,7 +806,7 @@ void CatapultAnimation::tick(uint32_t msPassed)
explosionEmitted = true; explosionEmitted = true;
Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, defendingStack) + Point(225, 225) - Point(126, 105); Point shotTarget = owner.stacksController->getStackPositionAtHex(dest, defendingStack) + Point(225, 225) - Point(126, 105);
std::string soundFilename = (catapultDamage > 0) ? "WALLHIT" : "WALLMISS"; auto soundFilename = AudioPath::builtin((catapultDamage > 0) ? "WALLHIT" : "WALLMISS");
AnimationPath effectFilename = AnimationPath::builtin((catapultDamage > 0) ? "SGEXPL" : "CSGRCK"); AnimationPath effectFilename = AnimationPath::builtin((catapultDamage > 0) ? "SGEXPL" : "CSGRCK");
CCS->soundh->playSound( soundFilename ); CCS->soundh->playSound( soundFilename );
+2 -2
View File
@@ -69,11 +69,11 @@ class StackActionAnimation : public BattleStackAnimation
{ {
ECreatureAnimType nextGroup; ECreatureAnimType nextGroup;
ECreatureAnimType currGroup; ECreatureAnimType currGroup;
std::string sound; AudioPath sound;
public: public:
void setNextGroup( ECreatureAnimType group ); void setNextGroup( ECreatureAnimType group );
void setGroup( ECreatureAnimType group ); void setGroup( ECreatureAnimType group );
void setSound( std::string sound ); void setSound( const AudioPath & sound );
ECreatureAnimType getGroup() const; ECreatureAnimType getGroup() const;
+8 -8
View File
@@ -41,10 +41,10 @@ BattleEffectsController::BattleEffectsController(BattleInterface & owner):
void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHex & destTile) void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHex & destTile)
{ {
displayEffect(effect, "", destTile); displayEffect(effect, AudioPath(), destTile);
} }
void BattleEffectsController::displayEffect(EBattleEffect effect, std::string soundFile, const BattleHex & destTile) void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile)
{ {
size_t effectID = static_cast<size_t>(effect); size_t effectID = static_cast<size_t>(effect);
@@ -69,22 +69,22 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
switch(static_cast<BonusType>(bte.effect)) switch(static_cast<BonusType>(bte.effect))
{ {
case BonusType::HP_REGENERATION: case BonusType::HP_REGENERATION:
displayEffect(EBattleEffect::REGENERATION, "REGENER", stack->getPosition()); displayEffect(EBattleEffect::REGENERATION, AudioPath::builtin("REGENER"), stack->getPosition());
break; break;
case BonusType::MANA_DRAIN: case BonusType::MANA_DRAIN:
displayEffect(EBattleEffect::MANA_DRAIN, "MANADRAI", stack->getPosition()); displayEffect(EBattleEffect::MANA_DRAIN, AudioPath::builtin("MANADRAI"), stack->getPosition());
break; break;
case BonusType::POISON: case BonusType::POISON:
displayEffect(EBattleEffect::POISON, "POISON", stack->getPosition()); displayEffect(EBattleEffect::POISON, AudioPath::builtin("POISON"), stack->getPosition());
break; break;
case BonusType::FEAR: case BonusType::FEAR:
displayEffect(EBattleEffect::FEAR, "FEAR", stack->getPosition()); displayEffect(EBattleEffect::FEAR, AudioPath::builtin("FEAR"), stack->getPosition());
break; break;
case BonusType::MORALE: case BonusType::MORALE:
{ {
std::string hlp = CGI->generaltexth->allTexts[33]; std::string hlp = CGI->generaltexth->allTexts[33];
boost::algorithm::replace_first(hlp,"%s",(stack->getName())); boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
displayEffect(EBattleEffect::GOOD_MORALE, "GOODMRLE", stack->getPosition()); displayEffect(EBattleEffect::GOOD_MORALE, AudioPath::builtin("GOODMRLE"), stack->getPosition());
owner.appendBattleLog(hlp); owner.appendBattleLog(hlp);
break; break;
} }
@@ -107,7 +107,7 @@ void BattleEffectsController::startAction(const BattleAction & action)
break; break;
case EActionType::BAD_MORALE: case EActionType::BAD_MORALE:
owner.appendBattleLog(stack->formatGeneralMessage(-34)); owner.appendBattleLog(stack->formatGeneralMessage(-34));
displayEffect(EBattleEffect::BAD_MORALE, "BADMRLE", stack->getPosition()); displayEffect(EBattleEffect::BAD_MORALE, AudioPath::builtin("BADMRLE"), stack->getPosition());
break; break;
} }
+2 -1
View File
@@ -11,6 +11,7 @@
#include "../../lib/battle/BattleHex.h" #include "../../lib/battle/BattleHex.h"
#include "../../lib/Point.h" #include "../../lib/Point.h"
#include "../../lib/filesystem/ResourcePath.h"
#include "BattleConstants.h" #include "BattleConstants.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -64,7 +65,7 @@ public:
//displays custom effect on the battlefield //displays custom effect on the battlefield
void displayEffect(EBattleEffect effect, const BattleHex & destTile); void displayEffect(EBattleEffect effect, const BattleHex & destTile);
void displayEffect(EBattleEffect effect, std::string soundFile, const BattleHex & destTile); void displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile);
void battleTriggerEffect(const BattleTriggerEffect & bte); void battleTriggerEffect(const BattleTriggerEffect & bte);
+2 -2
View File
@@ -353,7 +353,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
if(!spell) if(!spell)
return; return;
const std::string & castSoundPath = spell->getCastSound(); const AudioPath & castSoundPath = spell->getCastSound();
if (!castSoundPath.empty()) if (!castSoundPath.empty())
{ {
@@ -419,7 +419,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
if (!sc->resistedCres.empty()) if (!sc->resistedCres.empty())
{ {
addToAnimationStage(EAnimationEvents::HIT, [=](){ addToAnimationStage(EAnimationEvents::HIT, [=](){
CCS->soundh->playSound("MAGICRES"); CCS->soundh->playSound(AudioPath::builtin("MAGICRES"));
}); });
} }
+4 -4
View File
@@ -580,7 +580,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
break; break;
} }
CCS->musich->playMusic("Music/Win Battle", false, true); CCS->musich->playMusic(AudioPath::builtin("Music/Win Battle"), false, true);
CCS->videoh->open(VideoPath::builtin("WIN3.BIK")); CCS->videoh->open(VideoPath::builtin("WIN3.BIK"));
std::string str = CGI->generaltexth->allTexts[text]; std::string str = CGI->generaltexth->allTexts[text];
@@ -597,19 +597,19 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
else // we lose else // we lose
{ {
int text = 311; int text = 311;
std::string musicName = "Music/LoseCombat"; AudioPath musicName = AudioPath::builtin("Music/LoseCombat");
VideoPath videoName = VideoPath::builtin("LBSTART.BIK"); VideoPath videoName = VideoPath::builtin("LBSTART.BIK");
switch(br.result) switch(br.result)
{ {
case EBattleResult::NORMAL: case EBattleResult::NORMAL:
break; break;
case EBattleResult::ESCAPE: case EBattleResult::ESCAPE:
musicName = "Music/Retreat Battle"; musicName = AudioPath::builtin("Music/Retreat Battle");
videoName = VideoPath::builtin("RTSTART.BIK"); videoName = VideoPath::builtin("RTSTART.BIK");
text = 310; text = 310;
break; break;
case EBattleResult::SURRENDER: case EBattleResult::SURRENDER:
musicName = "Music/Surrender Battle"; musicName = AudioPath::builtin("Music/Surrender Battle");
videoName = VideoPath::builtin("SURRENDER.BIK"); videoName = VideoPath::builtin("SURRENDER.BIK");
text = 309; text = 309;
break; break;
+1 -1
View File
@@ -340,7 +340,7 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
for (auto attackInfo : ca.attackedParts) for (auto attackInfo : ca.attackedParts)
positions.push_back(owner.stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120)); positions.push_back(owner.stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120));
CCS->soundh->playSound( "WALLHIT" ); CCS->soundh->playSound( AudioPath::builtin("WALLHIT") );
owner.stacksController->addNewAnim(new EffectAnimation(owner, AnimationPath::builtin("SGEXPL.DEF"), positions)); owner.stacksController->addNewAnim(new EffectAnimation(owner, AnimationPath::builtin("SGEXPL.DEF"), positions));
} }
+6 -6
View File
@@ -462,7 +462,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
addNewAnim(new HittedAnimation(owner, attackedInfo.defender)); addNewAnim(new HittedAnimation(owner, attackedInfo.defender));
if (attackedInfo.fireShield) if (attackedInfo.fireShield)
owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, "FIRESHIE", attackedInfo.attacker->getPosition()); owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, AudioPath::builtin("FIRESHIE"), attackedInfo.attacker->getPosition());
if (attackedInfo.spellEffect != SpellID::NONE) if (attackedInfo.spellEffect != SpellID::NONE)
{ {
@@ -481,7 +481,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
if (attackedInfo.rebirth) if (attackedInfo.rebirth)
{ {
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){ owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
owner.effectsController->displayEffect(EBattleEffect::RESURRECT, "RESURECT", attackedInfo.defender->getPosition()); owner.effectsController->displayEffect(EBattleEffect::RESURRECT, AudioPath::builtin("RESURECT"), attackedInfo.defender->getPosition());
addNewAnim(new ResurrectionAnimation(owner, attackedInfo.defender)); addNewAnim(new ResurrectionAnimation(owner, attackedInfo.defender));
}); });
} }
@@ -594,7 +594,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
{ {
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() { owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
owner.appendBattleLog(info.attacker->formatGeneralMessage(-45)); owner.appendBattleLog(info.attacker->formatGeneralMessage(-45));
owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, "GOODLUCK", attacker->getPosition()); owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, AudioPath::builtin("GOODLUCK"), attacker->getPosition());
}); });
} }
@@ -602,7 +602,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
{ {
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() { owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
owner.appendBattleLog(info.attacker->formatGeneralMessage(-44)); owner.appendBattleLog(info.attacker->formatGeneralMessage(-44));
owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, "BADLUCK", attacker->getPosition()); owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, AudioPath::builtin("BADLUCK"), attacker->getPosition());
}); });
} }
@@ -610,7 +610,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
{ {
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() { owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
owner.appendBattleLog(info.attacker->formatGeneralMessage(365)); owner.appendBattleLog(info.attacker->formatGeneralMessage(365));
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, "DEATHBLO", defender->getPosition()); owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, AudioPath::builtin("DEATHBLO"), defender->getPosition());
}); });
for(auto elem : info.secondaryDefender) for(auto elem : info.secondaryDefender)
@@ -645,7 +645,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
{ {
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]() owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]()
{ {
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, "DRAINLIF", attacker->getPosition()); owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, AudioPath::builtin("DRAINLIF"), attacker->getPosition());
}); });
} }
+1 -1
View File
@@ -114,7 +114,7 @@ CBonusSelection::CBonusSelection()
} }
if (!getCampaign()->getMusic().empty()) if (!getCampaign()->getMusic().empty())
CCS->musich->playMusic( "Music/" + getCampaign()->getMusic(), true, false); CCS->musich->playMusic( getCampaign()->getMusic(), true, false);
} }
void CBonusSelection::createBonusesIcons() void CBonusSelection::createBonusesIcons()
+1 -1
View File
@@ -339,7 +339,7 @@ void CChatBox::keyPressed(EShortcut key)
void CChatBox::addNewMessage(const std::string & text) void CChatBox::addNewMessage(const std::string & text)
{ {
CCS->soundh->playSound("CHAT"); CCS->soundh->playSound(AudioPath::builtin("CHAT"));
chatHistory->setText(chatHistory->label->getText() + text + "\n"); chatHistory->setText(chatHistory->label->getText() + text + "\n");
if(chatHistory->slider) if(chatHistory->slider)
chatHistory->slider->scrollToMax(); chatHistory->slider->scrollToMax();
+3 -3
View File
@@ -75,7 +75,7 @@ CCampaignScreen::CCampaignScreen(const JsonNode & config)
void CCampaignScreen::activate() void CCampaignScreen::activate()
{ {
CCS->musich->playMusic("Music/MainMenu", true, false); CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, false);
CWindowObject::activate(); CWindowObject::activate();
} }
@@ -129,12 +129,12 @@ void CCampaignScreen::CCampaignButton::show(Canvas & to)
// Play the campaign button video when the mouse cursor is placed over the button // Play the campaign button video when the mouse cursor is placed over the button
if(isHovered()) if(isHovered())
{ {
if(CCS->videoh->fname != video) if(CCS->videoh->fname != video.addPrefix("VIDEO/"))
CCS->videoh->open(video); CCS->videoh->open(video);
CCS->videoh->update(pos.x, pos.y, to.getInternalSurface(), true, false); // plays sequentially frame by frame, starts at the beginning when the video is over CCS->videoh->update(pos.x, pos.y, to.getInternalSurface(), true, false); // plays sequentially frame by frame, starts at the beginning when the video is over
} }
else if(CCS->videoh->fname == video) // When you got out of the bounds of the button then close the video else if(CCS->videoh->fname == video.addPrefix("VIDEO/")) // When you got out of the bounds of the button then close the video
{ {
CCS->videoh->close(); CCS->videoh->close();
redraw(); redraw();
+1 -1
View File
@@ -114,7 +114,7 @@ void CMenuScreen::show(Canvas & to)
void CMenuScreen::activate() void CMenuScreen::activate()
{ {
CCS->musich->playMusic("Music/MainMenu", true, true); CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
if(!config["video"].isNull()) if(!config["video"].isNull())
CCS->videoh->open(VideoPath::fromJson(config["video"]["name"])); CCS->videoh->open(VideoPath::fromJson(config["video"]["name"]));
CIntObject::activate(); CIntObject::activate();
+1 -1
View File
@@ -28,7 +28,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f
updateShadow(); updateShadow();
CCS->videoh->open(spe.prologVideo); CCS->videoh->open(spe.prologVideo);
CCS->musich->playMusic("Music/" + spe.prologMusic, true, true); CCS->musich->playMusic(spe.prologMusic, true, true);
// MPTODO: Custom campaign crashing on this? // MPTODO: Custom campaign crashing on this?
// voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo)); // voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo));
+1 -1
View File
@@ -182,7 +182,7 @@ void CAnimation::init()
if (vstd::contains(graphics->imageLists, name.getName())) if (vstd::contains(graphics->imageLists, name.getName()))
initFromJson(graphics->imageLists[name.getName()]); initFromJson(graphics->imageLists[name.getName()]);
auto jsonResource = name.toType<EResType::TEXT>(); auto jsonResource = name.toType<EResType::JSON>();
auto configList = CResourceHandler::get()->getResourcesWithName(jsonResource); auto configList = CResourceHandler::get()->getResourcesWithName(jsonResource);
for(auto & loader : configList) for(auto & loader : configList)
-1
View File
@@ -45,7 +45,6 @@ public:
virtual bool hasSchool(SpellSchool school) const = 0; virtual bool hasSchool(SpellSchool school) const = 0;
virtual void forEachSchool(const SchoolCallback & cb) const = 0; virtual void forEachSchool(const SchoolCallback & cb) const = 0;
virtual const std::string & getCastSound() const = 0;
virtual int32_t getCost(const int32_t skillLevel) const = 0; virtual int32_t getCost(const int32_t skillLevel) const = 0;
virtual int32_t getBasePower() const = 0; virtual int32_t getBasePower() const = 0;
+8 -11
View File
@@ -955,17 +955,14 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
creature->special = config["special"].Bool() || config["disabled"].Bool(); creature->special = config["special"].Bool() || config["disabled"].Bool();
const JsonNode & sounds = config["sound"]; const JsonNode & sounds = config["sound"];
creature->sounds.attack = AudioPath::fromJson(sounds["attack"]);
#define GET_SOUND_VALUE(value_name) creature->sounds.value_name = sounds[#value_name].String() creature->sounds.defend = AudioPath::fromJson(sounds["defend"]);
GET_SOUND_VALUE(attack); creature->sounds.killed = AudioPath::fromJson(sounds["killed"]);
GET_SOUND_VALUE(defend); creature->sounds.move = AudioPath::fromJson(sounds["move"]);
GET_SOUND_VALUE(killed); creature->sounds.shoot = AudioPath::fromJson(sounds["shoot"]);
GET_SOUND_VALUE(move); creature->sounds.wince = AudioPath::fromJson(sounds["wince"]);
GET_SOUND_VALUE(shoot); creature->sounds.startMoving = AudioPath::fromJson(sounds["startMoving"]);
GET_SOUND_VALUE(wince); creature->sounds.endMoving = AudioPath::fromJson(sounds["endMoving"]);
GET_SOUND_VALUE(startMoving);
GET_SOUND_VALUE(endMoving);
#undef GET_SOUND_VALUE
} }
void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode & input) const void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode & input) const
+8 -8
View File
@@ -132,14 +132,14 @@ public:
//sound info //sound info
struct CreatureBattleSounds struct CreatureBattleSounds
{ {
std::string attack; AudioPath attack;
std::string defend; AudioPath defend;
std::string killed; // was killed or died AudioPath killed; // was killed or died
std::string move; AudioPath move;
std::string shoot; // range attack AudioPath shoot; // range attack
std::string wince; // attacked but did not die AudioPath wince; // attacked but did not die
std::string startMoving; AudioPath startMoving;
std::string endMoving; AudioPath endMoving;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
+4 -4
View File
@@ -48,7 +48,7 @@ void CGeneralTextHandler::detectInstallParameters()
"ukrainian" "ukrainian"
} }; } };
if(!CResourceHandler::get("core")->existsResource(ResourcePath("DATA/GENRLTXT.TXT", EResType::TEXT))) if(!CResourceHandler::get("core")->existsResource(TextPath::builtin("DATA/GENRLTXT.TXT")))
{ {
Settings language = settings.write["session"]["language"]; Settings language = settings.write["session"]["language"];
language->String() = "english"; language->String() = "english";
@@ -64,7 +64,7 @@ void CGeneralTextHandler::detectInstallParameters()
// load file that will be used for footprint generation // load file that will be used for footprint generation
// this is one of the most text-heavy files in game and consists solely from translated texts // this is one of the most text-heavy files in game and consists solely from translated texts
auto resource = CResourceHandler::get("core")->load(ResourcePath("DATA/GENRLTXT.TXT", EResType::TEXT)); auto resource = CResourceHandler::get("core")->load(TextPath::builtin("DATA/GENRLTXT.TXT"));
std::array<size_t, 256> charCount{}; std::array<size_t, 256> charCount{};
std::array<double, 16> footprint{}; std::array<double, 16> footprint{};
@@ -429,7 +429,7 @@ CGeneralTextHandler::CGeneralTextHandler():
readToVector("core.mineevnt", "DATA/MINEEVNT.TXT" ); readToVector("core.mineevnt", "DATA/MINEEVNT.TXT" );
static const char * QE_MOD_COMMANDS = "DATA/QECOMMANDS.TXT"; static const char * QE_MOD_COMMANDS = "DATA/QECOMMANDS.TXT";
if (CResourceHandler::get()->existsResource(ResourcePath(QE_MOD_COMMANDS, EResType::TEXT))) if (CResourceHandler::get()->existsResource(TextPath::builtin(QE_MOD_COMMANDS)))
readToVector("vcmi.quickExchange", QE_MOD_COMMANDS); readToVector("vcmi.quickExchange", QE_MOD_COMMANDS);
{ {
@@ -574,7 +574,7 @@ CGeneralTextHandler::CGeneralTextHandler():
} }
if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS)) if (VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS))
{ {
if(CResourceHandler::get()->existsResource(ResourcePath("DATA/ZNPC00.TXT", EResType::TEXT))) if(CResourceHandler::get()->existsResource(TextPath::builtin("DATA/ZNPC00.TXT")))
readToVector("vcmi.znpc00", "DATA/ZNPC00.TXT" ); readToVector("vcmi.znpc00", "DATA/ZNPC00.TXT" );
} }
} }
+1 -1
View File
@@ -878,7 +878,7 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source) const
readIcon(source["icons"]["fort"]["built"], info.iconSmall[1][1], info.iconLarge[1][1]); readIcon(source["icons"]["fort"]["built"], info.iconSmall[1][1], info.iconLarge[1][1]);
info.hallBackground = ImagePath::fromJson(source["hallBackground"]); info.hallBackground = ImagePath::fromJson(source["hallBackground"]);
info.musicTheme = source["musicTheme"].String(); info.musicTheme = AudioPath::fromJson(source["musicTheme"]);
info.townBackground = ImagePath::fromJson(source["townBackground"]); info.townBackground = ImagePath::fromJson(source["townBackground"]);
info.guildWindow = ImagePath::fromJson(source["guildWindow"]); info.guildWindow = ImagePath::fromJson(source["guildWindow"]);
info.buildingsIcons = AnimationPath::fromJson(source["buildingsIcons"]); info.buildingsIcons = AnimationPath::fromJson(source["buildingsIcons"]);
+1 -1
View File
@@ -305,7 +305,7 @@ public:
std::string iconSmall[2][2]; /// icon names used during loading std::string iconSmall[2][2]; /// icon names used during loading
std::string iconLarge[2][2]; std::string iconLarge[2][2];
VideoPath tavernVideo; VideoPath tavernVideo;
std::string musicTheme; AudioPath musicTheme;
ImagePath townBackground; ImagePath townBackground;
ImagePath guildBackground; ImagePath guildBackground;
ImagePath guildWindow; ImagePath guildWindow;
+1 -1
View File
@@ -116,7 +116,7 @@ public:
virtual void showTavernWindow(const CGObjectInstance *townOrTavern){}; virtual void showTavernWindow(const CGObjectInstance *townOrTavern){};
virtual void showThievesGuildWindow (const CGObjectInstance * obj){}; virtual void showThievesGuildWindow (const CGObjectInstance * obj){};
virtual void showQuestLog(){}; virtual void showQuestLog(){};
virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell virtual void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID){}; //called when a hero casts a spell
virtual void tileHidden(const std::unordered_set<int3> &pos){}; virtual void tileHidden(const std::unordered_set<int3> &pos){};
virtual void tileRevealed(const std::unordered_set<int3> &pos){}; virtual void tileRevealed(const std::unordered_set<int3> &pos){};
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
+2 -2
View File
@@ -1036,13 +1036,13 @@ namespace
std::string testAnimation(const std::string & path, const std::string & scope) std::string testAnimation(const std::string & path, const std::string & scope)
{ {
TEST_FILE(scope, "Sprites/", path, EResType::ANIMATION); TEST_FILE(scope, "Sprites/", path, EResType::ANIMATION);
TEST_FILE(scope, "Sprites/", path, EResType::TEXT); TEST_FILE(scope, "Sprites/", path, EResType::JSON);
return "Animation file \"" + path + "\" was not found"; return "Animation file \"" + path + "\" was not found";
} }
std::string textFile(const JsonNode & node) std::string textFile(const JsonNode & node)
{ {
TEST_FILE(node.meta, "", node.String(), EResType::TEXT); TEST_FILE(node.meta, "", node.String(), EResType::JSON);
return "Text file \"" + node.String() + "\" was not found"; return "Text file \"" + node.String() + "\" was not found";
} }
+1 -1
View File
@@ -32,7 +32,7 @@ public:
Obstacle obstacle; Obstacle obstacle;
si32 iconIndex; si32 iconIndex;
std::string identifier; std::string identifier;
std::string appearSound; AudioPath appearSound;
AnimationPath appearAnimation; AnimationPath appearAnimation;
AnimationPath animation; AnimationPath animation;
std::vector<TerrainId> allowedTerrains; std::vector<TerrainId> allowedTerrains;
+3 -3
View File
@@ -27,10 +27,10 @@ TerrainType * TerrainTypeHandler::loadFromJson( const std::string & scope, const
info->identifier = identifier; info->identifier = identifier;
info->modScope = scope; info->modScope = scope;
info->moveCost = static_cast<int>(json["moveCost"].Integer()); info->moveCost = static_cast<int>(json["moveCost"].Integer());
info->musicFilename = json["music"].String(); info->musicFilename = AudioPath::fromJson(json["music"]);
info->tilesFilename = AnimationPath::fromJson(json["tiles"]); info->tilesFilename = AnimationPath::fromJson(json["tiles"]);
info->horseSound = json["horseSound"].String(); info->horseSound = AudioPath::fromJson(json["horseSound"]);
info->horseSoundPenalty = json["horseSoundPenalty"].String(); info->horseSoundPenalty = AudioPath::fromJson(json["horseSoundPenalty"]);
info->transitionRequired = json["transitionRequired"].Bool(); info->transitionRequired = json["transitionRequired"].Bool();
info->terrainViewPatterns = json["terrainViewPatterns"].String(); info->terrainViewPatterns = json["terrainViewPatterns"].String();
+3 -3
View File
@@ -67,11 +67,11 @@ public:
ColorRGBA minimapBlocked; ColorRGBA minimapBlocked;
ColorRGBA minimapUnblocked; ColorRGBA minimapUnblocked;
std::string shortIdentifier; std::string shortIdentifier;
std::string musicFilename; AudioPath musicFilename;
AnimationPath tilesFilename; AnimationPath tilesFilename;
std::string terrainViewPatterns; std::string terrainViewPatterns;
std::string horseSound; AudioPath horseSound;
std::string horseSoundPenalty; AudioPath horseSoundPenalty;
std::vector<TerrainPaletteAnimation> paletteAnimation; std::vector<TerrainPaletteAnimation> paletteAnimation;
+4 -4
View File
@@ -70,7 +70,7 @@ const AnimationPath & CObstacleInstance::getAppearAnimation() const
return getInfo().appearAnimation; return getInfo().appearAnimation;
} }
const std::string & CObstacleInstance::getAppearSound() const const AudioPath & CObstacleInstance::getAppearSound() const
{ {
return getInfo().appearSound; return getInfo().appearSound;
} }
@@ -118,7 +118,7 @@ void CObstacleInstance::serializeJson(JsonSerializeFormat & handler)
//We need only a subset of obstacle info for correct render //We need only a subset of obstacle info for correct render
handler.serializeInt("position", pos); handler.serializeInt("position", pos);
handler.serializeString("appearSound", obstacleInfo.appearSound); handler.serializeStruct("appearSound", obstacleInfo.appearSound);
handler.serializeStruct("appearAnimation", obstacleInfo.appearAnimation); handler.serializeStruct("appearAnimation", obstacleInfo.appearAnimation);
handler.serializeStruct("animation", obstacleInfo.animation); handler.serializeStruct("animation", obstacleInfo.animation);
handler.serializeInt("animationYOffset", animationYOffset); handler.serializeInt("animationYOffset", animationYOffset);
@@ -213,7 +213,7 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
handler.serializeBool("removeOnTrigger", removeOnTrigger); handler.serializeBool("removeOnTrigger", removeOnTrigger);
handler.serializeBool("nativeVisible", nativeVisible); handler.serializeBool("nativeVisible", nativeVisible);
handler.serializeString("appearSound", appearSound); handler.serializeStruct("appearSound", appearSound);
handler.serializeStruct("appearAnimation", appearAnimation); handler.serializeStruct("appearAnimation", appearAnimation);
handler.serializeStruct("animation", animation); handler.serializeStruct("animation", animation);
@@ -249,7 +249,7 @@ const AnimationPath & SpellCreatedObstacle::getAppearAnimation() const
return appearAnimation; return appearAnimation;
} }
const std::string & SpellCreatedObstacle::getAppearSound() const const AudioPath & SpellCreatedObstacle::getAppearSound() const
{ {
return appearSound; return appearSound;
} }
+3 -3
View File
@@ -54,7 +54,7 @@ struct DLL_LINKAGE CObstacleInstance
//Client helper functions, make it easier to render animations //Client helper functions, make it easier to render animations
virtual const AnimationPath & getAnimation() const; virtual const AnimationPath & getAnimation() const;
virtual const AnimationPath & getAppearAnimation() const; virtual const AnimationPath & getAppearAnimation() const;
virtual const std::string & getAppearSound() const; virtual const AudioPath & getAppearSound() const;
virtual int getAnimationYOffset(int imageHeight) const; virtual int getAnimationYOffset(int imageHeight) const;
@@ -88,7 +88,7 @@ struct DLL_LINKAGE SpellCreatedObstacle : CObstacleInstance
bool revealed; bool revealed;
bool nativeVisible; //Should native terrain creatures reveal obstacle bool nativeVisible; //Should native terrain creatures reveal obstacle
std::string appearSound; AudioPath appearSound;
AnimationPath appearAnimation; AnimationPath appearAnimation;
AnimationPath animation; AnimationPath animation;
@@ -110,7 +110,7 @@ struct DLL_LINKAGE SpellCreatedObstacle : CObstacleInstance
//Client helper functions, make it easier to render animations //Client helper functions, make it easier to render animations
const AnimationPath & getAnimation() const override; const AnimationPath & getAnimation() const override;
const AnimationPath & getAppearAnimation() const override; const AnimationPath & getAppearAnimation() const override;
const std::string & getAppearSound() const override; const AudioPath & getAppearSound() const override;
int getAnimationYOffset(int imageHeight) const override; int getAnimationYOffset(int imageHeight) const override;
void fromInfo(const ObstacleChanges & info); void fromInfo(const ObstacleChanges & info);
+4 -4
View File
@@ -152,7 +152,7 @@ void CampaignHandler::readHeaderFromJson(CampaignHeader & ret, JsonNode & reader
ret.name = reader["name"].String(); ret.name = reader["name"].String();
ret.description = reader["description"].String(); ret.description = reader["description"].String();
ret.difficultyChoosenByPlayer = reader["allowDifficultySelection"].Bool(); ret.difficultyChoosenByPlayer = reader["allowDifficultySelection"].Bool();
ret.music = reader["music"].String(); ret.music = AudioPath::fromJson(reader["music"]);
ret.filename = filename; ret.filename = filename;
ret.modName = modName; ret.modName = modName;
ret.encoding = encoding; ret.encoding = encoding;
@@ -167,7 +167,7 @@ CampaignScenario CampaignHandler::readScenarioFromJson(JsonNode & reader)
if(ret.hasPrologEpilog) if(ret.hasPrologEpilog)
{ {
ret.prologVideo = VideoPath::fromJson(identifier["video"]); ret.prologVideo = VideoPath::fromJson(identifier["video"]);
ret.prologMusic = identifier["music"].String(); ret.prologMusic = AudioPath::fromJson(identifier["music"]);
ret.prologText = identifier["text"].String(); ret.prologText = identifier["text"].String();
} }
return ret; return ret;
@@ -599,10 +599,10 @@ VideoPath CampaignHandler::prologVideoName(ui8 index)
return VideoPath(); return VideoPath();
} }
std::string CampaignHandler::prologMusicName(ui8 index) AudioPath CampaignHandler::prologMusicName(ui8 index)
{ {
std::vector<std::string> music; std::vector<std::string> music;
return VLC->generaltexth->translate("core.cmpmusic." + std::to_string(static_cast<int>(index))); return AudioPath::builtinTODO(VLC->generaltexth->translate("core.cmpmusic." + std::to_string(static_cast<int>(index))));
} }
std::string CampaignHandler::prologVoiceName(ui8 index) std::string CampaignHandler::prologVoiceName(ui8 index)
+1 -1
View File
@@ -34,7 +34,7 @@ class DLL_LINKAGE CampaignHandler
static std::vector<std::vector<ui8>> getFile(std::unique_ptr<CInputStream> file, bool headerOnly); static std::vector<std::vector<ui8>> getFile(std::unique_ptr<CInputStream> file, bool headerOnly);
static VideoPath prologVideoName(ui8 index); static VideoPath prologVideoName(ui8 index);
static std::string prologMusicName(ui8 index); static AudioPath prologMusicName(ui8 index);
static std::string prologVoiceName(ui8 index); static std::string prologVoiceName(ui8 index);
public: public:
+1 -1
View File
@@ -17,7 +17,7 @@ struct DLL_LINKAGE CampaignScenarioPrologEpilog
{ {
bool hasPrologEpilog = false; bool hasPrologEpilog = false;
VideoPath prologVideo; // from CmpMovie.txt VideoPath prologVideo; // from CmpMovie.txt
std::string prologMusic; // from CmpMusic.txt AudioPath prologMusic; // from CmpMusic.txt
std::string prologText; std::string prologText;
template <typename Handler> void serialize(Handler &h, const int formatVersion) template <typename Handler> void serialize(Handler &h, const int formatVersion)
+1 -1
View File
@@ -159,7 +159,7 @@ std::string CampaignHeader::getEncoding() const
return encoding; return encoding;
} }
std::string CampaignHeader::getMusic() const AudioPath CampaignHeader::getMusic() const
{ {
return music; return music;
} }
+2 -2
View File
@@ -76,7 +76,7 @@ class DLL_LINKAGE CampaignHeader : public boost::noncopyable
CampaignRegions campaignRegions; CampaignRegions campaignRegions;
std::string name; std::string name;
std::string description; std::string description;
std::string music; AudioPath music;
std::string filename; std::string filename;
std::string modName; std::string modName;
std::string encoding; std::string encoding;
@@ -95,7 +95,7 @@ public:
std::string getFilename() const; std::string getFilename() const;
std::string getModName() const; std::string getModName() const;
std::string getEncoding() const; std::string getEncoding() const;
std::string getMusic() const; AudioPath getMusic() const;
const CampaignRegions & getRegions() const; const CampaignRegions & getRegions() const;
+1 -1
View File
@@ -103,7 +103,7 @@ std::unordered_map<ResourcePath, boost::filesystem::path> CFilesystemLoader::lis
{ {
static const EResType initArray[] = { static const EResType initArray[] = {
EResType::DIRECTORY, EResType::DIRECTORY,
EResType::TEXT, EResType::JSON,
EResType::ARCHIVE_LOD, EResType::ARCHIVE_LOD,
EResType::ARCHIVE_VID, EResType::ARCHIVE_VID,
EResType::ARCHIVE_SND, EResType::ARCHIVE_SND,
+3 -3
View File
@@ -113,10 +113,10 @@ void CFilesystemGenerator::loadArchive(const std::string &mountPoint, const Json
void CFilesystemGenerator::loadJsonMap(const std::string &mountPoint, const JsonNode & config) void CFilesystemGenerator::loadJsonMap(const std::string &mountPoint, const JsonNode & config)
{ {
std::string URI = prefix + config["path"].String(); std::string URI = prefix + config["path"].String();
auto filename = CResourceHandler::get("initial")->getResourceName(ResourcePath(URI, EResType::TEXT)); auto filename = CResourceHandler::get("initial")->getResourceName(JsonPath::builtin(URI));
if (filename) if (filename)
{ {
auto configData = CResourceHandler::get("initial")->load(ResourcePath(URI, EResType::TEXT))->readAll(); auto configData = CResourceHandler::get("initial")->load(JsonPath::builtin(URI))->readAll();
const JsonNode configInitial(reinterpret_cast<char *>(configData.first.get()), configData.second); const JsonNode configInitial(reinterpret_cast<char *>(configData.first.get()), configData.second);
filesystem->addLoader(new CMappedFileLoader(mountPoint, configInitial), false); filesystem->addLoader(new CMappedFileLoader(mountPoint, configInitial), false);
} }
@@ -210,7 +210,7 @@ ISimpleResourceLoader * CResourceHandler::get(const std::string & identifier)
void CResourceHandler::load(const std::string &fsConfigURI, bool extractArchives) void CResourceHandler::load(const std::string &fsConfigURI, bool extractArchives)
{ {
auto fsConfigData = get("initial")->load(ResourcePath(fsConfigURI, EResType::TEXT))->readAll(); auto fsConfigData = get("initial")->load(JsonPath::builtin(fsConfigURI))->readAll();
const JsonNode fsConfig(reinterpret_cast<char *>(fsConfigData.first.get()), fsConfigData.second); const JsonNode fsConfig(reinterpret_cast<char *>(fsConfigData.first.get()), fsConfigData.second);
+2 -1
View File
@@ -94,7 +94,7 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
static const std::map<std::string, EResType> stringToRes = static const std::map<std::string, EResType> stringToRes =
{ {
{".TXT", EResType::TEXT}, {".TXT", EResType::TEXT},
{".JSON", EResType::TEXT}, {".JSON", EResType::JSON},
{".DEF", EResType::ANIMATION}, {".DEF", EResType::ANIMATION},
{".MSK", EResType::MASK}, {".MSK", EResType::MASK},
{".MSG", EResType::MASK}, {".MSG", EResType::MASK},
@@ -148,6 +148,7 @@ std::string EResTypeHelper::getEResTypeAsString(EResType type)
static const std::map<EResType, std::string> stringToRes = static const std::map<EResType, std::string> stringToRes =
{ {
MAP_ENUM(TEXT) MAP_ENUM(TEXT)
MAP_ENUM(JSON)
MAP_ENUM(ANIMATION) MAP_ENUM(ANIMATION)
MAP_ENUM(MASK) MAP_ENUM(MASK)
MAP_ENUM(CAMPAIGN) MAP_ENUM(CAMPAIGN)
+7
View File
@@ -140,6 +140,12 @@ public:
:ResourcePath("", Type) :ResourcePath("", Type)
{} {}
static ResourcePathTempl fromResource(const ResourcePath & resource)
{
assert(Type == resource.getType());
return ResourcePathTempl(resource);
}
static ResourcePathTempl builtin(const std::string & filename) static ResourcePathTempl builtin(const std::string & filename)
{ {
return ResourcePathTempl(filename, Type); return ResourcePathTempl(filename, Type);
@@ -177,6 +183,7 @@ using ImagePath = ResourcePathTempl<EResType::IMAGE>;
using TextPath = ResourcePathTempl<EResType::TEXT>; using TextPath = ResourcePathTempl<EResType::TEXT>;
using JsonPath = ResourcePathTempl<EResType::JSON>; using JsonPath = ResourcePathTempl<EResType::JSON>;
using VideoPath = ResourcePathTempl<EResType::VIDEO>; using VideoPath = ResourcePathTempl<EResType::VIDEO>;
using AudioPath = ResourcePathTempl<EResType::SOUND>;
namespace EResTypeHelper namespace EResTypeHelper
{ {
@@ -83,13 +83,13 @@ void AObjectTypeHandler::init(const JsonNode & input)
} }
for(const JsonNode & node : input["sounds"]["ambient"].Vector()) for(const JsonNode & node : input["sounds"]["ambient"].Vector())
sounds.ambient.push_back(node.String()); sounds.ambient.push_back(AudioPath::fromJson(node));
for(const JsonNode & node : input["sounds"]["visit"].Vector()) for(const JsonNode & node : input["sounds"]["visit"].Vector())
sounds.visit.push_back(node.String()); sounds.visit.push_back(AudioPath::fromJson(node));
for(const JsonNode & node : input["sounds"]["removal"].Vector()) for(const JsonNode & node : input["sounds"]["removal"].Vector())
sounds.removal.push_back(node.String()); sounds.removal.push_back(AudioPath::fromJson(node));
if(input["aiValue"].isNull()) if(input["aiValue"].isNull())
aiValue = std::nullopt; aiValue = std::nullopt;
+5 -3
View File
@@ -9,13 +9,15 @@
*/ */
#pragma once #pragma once
#include "../filesystem/ResourcePath.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
struct SObjectSounds struct SObjectSounds
{ {
std::vector<std::string> ambient; std::vector<AudioPath> ambient;
std::vector<std::string> visit; std::vector<AudioPath> visit;
std::vector<std::string> removal; std::vector<AudioPath> removal;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
+3 -3
View File
@@ -214,7 +214,7 @@ std::string CGObjectInstance::getObjectName() const
return VLC->objtypeh->getObjectName(ID, subID); return VLC->objtypeh->getObjectName(ID, subID);
} }
std::optional<std::string> CGObjectInstance::getAmbientSound() const std::optional<AudioPath> CGObjectInstance::getAmbientSound() const
{ {
const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).ambient; const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).ambient;
if(!sounds.empty()) if(!sounds.empty())
@@ -223,7 +223,7 @@ std::optional<std::string> CGObjectInstance::getAmbientSound() const
return std::nullopt; return std::nullopt;
} }
std::optional<std::string> CGObjectInstance::getVisitSound() const std::optional<AudioPath> CGObjectInstance::getVisitSound() const
{ {
const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).visit; const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).visit;
if(!sounds.empty()) if(!sounds.empty())
@@ -232,7 +232,7 @@ std::optional<std::string> CGObjectInstance::getVisitSound() const
return std::nullopt; return std::nullopt;
} }
std::optional<std::string> CGObjectInstance::getRemovalSound() const std::optional<AudioPath> CGObjectInstance::getRemovalSound() const
{ {
const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).removal; const auto & sounds = VLC->objtypeh->getObjectSounds(ID, subID).removal;
if(!sounds.empty()) if(!sounds.empty())
+3 -3
View File
@@ -82,9 +82,9 @@ public:
virtual bool isTile2Terrain() const { return false; } virtual bool isTile2Terrain() const { return false; }
std::optional<std::string> getAmbientSound() const; std::optional<AudioPath> getAmbientSound() const;
std::optional<std::string> getVisitSound() const; std::optional<AudioPath> getVisitSound() const;
std::optional<std::string> getRemovalSound() const; std::optional<AudioPath> getRemovalSound() const;
/** VIRTUAL METHODS **/ /** VIRTUAL METHODS **/
+1 -1
View File
@@ -904,7 +904,7 @@ std::unique_ptr<CMapHeader> CMapLoaderJson::loadMapHeader()
JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename) JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename)
{ {
ResourcePath resource(archiveFilename, EResType::TEXT); JsonPath resource = JsonPath::builtin(archiveFilename);
if(!loader.existsResource(resource)) if(!loader.existsResource(resource))
throw std::runtime_error(archiveFilename+" not found"); throw std::runtime_error(archiveFilename+" not found");
+2 -2
View File
@@ -310,7 +310,7 @@ const std::string & CSpell::getIconScroll() const
return iconScroll; return iconScroll;
} }
const std::string & CSpell::getCastSound() const const AudioPath & CSpell::getCastSound() const
{ {
return castSound; return castSound;
} }
@@ -896,7 +896,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
} }
const JsonNode & soundsNode = json["sounds"]; const JsonNode & soundsNode = json["sounds"];
spell->castSound = soundsNode["cast"].String(); spell->castSound = AudioPath::fromJson(soundsNode["cast"]);
//load level attributes //load level attributes
const int levelsCount = GameConstants::SPELL_SCHOOL_LEVELS; const int levelsCount = GameConstants::SPELL_SCHOOL_LEVELS;
+2 -2
View File
@@ -262,7 +262,7 @@ public:
const std::string & getIconScenarioBonus() const; const std::string & getIconScenarioBonus() const;
const std::string & getIconScroll() const; const std::string & getIconScroll() const;
const std::string & getCastSound() const override; const AudioPath & getCastSound() const;
void updateFrom(const JsonNode & data); void updateFrom(const JsonNode & data);
void serializeJson(JsonSerializeFormat & handler); void serializeJson(JsonSerializeFormat & handler);
@@ -354,7 +354,7 @@ private:
std::string iconScroll; std::string iconScroll;
///sound related stuff ///sound related stuff
std::string castSound; AudioPath castSound;
std::vector<LevelInfo> levels; std::vector<LevelInfo> levels;
+1 -1
View File
@@ -85,7 +85,7 @@ void ObstacleSideOptions::serializeJson(JsonSerializeFormat & handler)
serializeRelativeShape(handler, "shape", shape); serializeRelativeShape(handler, "shape", shape);
serializeRelativeShape(handler, "range", range); serializeRelativeShape(handler, "range", range);
handler.serializeString("appearSound", appearSound); handler.serializeStruct("appearSound", appearSound);
handler.serializeStruct("appearAnimation", appearAnimation); handler.serializeStruct("appearAnimation", appearAnimation);
handler.serializeStruct("animation", animation); handler.serializeStruct("animation", animation);
+1 -1
View File
@@ -30,7 +30,7 @@ public:
RelativeShape shape; //shape of single obstacle relative to obstacle position RelativeShape shape; //shape of single obstacle relative to obstacle position
RelativeShape range; //position of obstacles relative to effect destination RelativeShape range; //position of obstacles relative to effect destination
std::string appearSound; AudioPath appearSound;
AnimationPath appearAnimation; AnimationPath appearAnimation;
AnimationPath animation; AnimationPath animation;
+1 -1
View File
@@ -583,7 +583,7 @@ void Animation::init()
source[defEntry.first].resize(defEntry.second); source[defEntry.first].resize(defEntry.second);
} }
ResourcePath resID(std::string("SPRITES/") + name, EResType::TEXT); JsonPath resID = JsonPath::builtin("SPRITES/" + name);
//if(vstd::contains(graphics->imageLists, resID.getName())) //if(vstd::contains(graphics->imageLists, resID.getName()))
//initFromJson(graphics->imageLists[resID.getName()]); //initFromJson(graphics->imageLists[resID.getName()]);
+1 -1
View File
@@ -90,7 +90,7 @@ TEST(MapFormat, Random)
static JsonNode getFromArchive(CZipLoader & archive, const std::string & archiveFilename) static JsonNode getFromArchive(CZipLoader & archive, const std::string & archiveFilename)
{ {
ResourcePath resource(archiveFilename, EResType::TEXT); JsonPath resource = JsonPath::builtin(archiveFilename);
if(!archive.existsResource(resource)) if(!archive.existsResource(resource))
throw std::runtime_error(archiveFilename + " not found"); throw std::runtime_error(archiveFilename + " not found");