1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- music player uses URI's instead of enum from music base

- #1045 and #1046 should be fixed
- moved pregame backgrounds to config/mainmenu
- animation can be overriden with .json multiple times
This commit is contained in:
Ivan Savenko 2012-08-06 07:34:37 +00:00
parent 385be09248
commit 708ad6ac7f
24 changed files with 212 additions and 256 deletions

View File

@ -2576,7 +2576,7 @@ int3 whereToExplore(HeroPtr h)
} }
catch(cannotFulfillGoalException &e) catch(cannotFulfillGoalException &e)
{ {
std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow], metryka taksówkowa std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow]
try try
{ {
return ai->explorationNewPoint(radius, h, tiles); return ai->explorationNewPoint(radius, h, tiles);

View File

@ -268,16 +268,16 @@ namespace vstd
//checks if a is between b and c //checks if a is between b and c
template <typename t1, typename t2, typename t3> template <typename t1, typename t2, typename t3>
bool isbetween(const t1 &a, const t2 &b, const t3 &c) bool isbetween(const t1 &value, const t2 &min, const t3 &max)
{ {
return a > b && a < c; return value > min && value < max;
} }
//checks if a is within b and c //checks if a is within b and c
template <typename t1, typename t2, typename t3> template <typename t1, typename t2, typename t3>
bool iswithin(const t1 &a, const t2 &b, const t3 &c) bool iswithin(const t1 &value, const t2 &min, const t3 &max)
{ {
return a >= b && a <= c; return value >= min && value <= max;
} }
template <typename t1, typename t2> template <typename t1, typename t2>

View File

@ -371,8 +371,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
CCS->musich->stopMusic(); CCS->musich->stopMusic();
int channel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds); int channel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds);
CCS->soundh->setCallback(channel, boost::bind(&CMusicHandler::playMusicFromSet, CCS->musich, CCS->musich->battleMusics, -1)); auto onIntroPlayed = []()
memset(stackCountOutsideHexes, 1, GameConstants::BFIELD_SIZE * sizeof(bool)); //initialize array with trues {
if (LOCPLINT->battleInt)
CCS->musich->playMusicFromSet("battle", true);
};
CCS->soundh->setCallback(channel, onIntroPlayed);
memset(stackCountOutsideHexes, 1, GameConstants::BFIELD_SIZE * sizeof(bool)); //initialize array with trues
currentAction = INVALID; currentAction = INVALID;
selectedAction = INVALID; selectedAction = INVALID;
@ -446,7 +452,7 @@ CBattleInterface::~CBattleInterface()
if(adventureInt && adventureInt->selection) if(adventureInt && adventureInt->selection)
{ {
int terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->tertype; int terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->tertype;
CCS->musich->playMusic(CCS->musich->terrainMusics[terrain], -1); CCS->musich->playMusicFromSet("terrain", terrain, true);
} }
} }

View File

@ -417,7 +417,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
case 2: text = 302; break; case 2: text = 302; break;
} }
CCS->musich->playMusic(musicBase::winBattle); CCS->musich->playMusic("Music/Win Battle", false);
CCS->videoh->open(VIDEO_WIN); CCS->videoh->open(VIDEO_WIN);
std::string str = CGI->generaltexth->allTexts[text]; std::string str = CGI->generaltexth->allTexts[text];
@ -437,21 +437,21 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
{ {
case 0: //normal victory case 0: //normal victory
{ {
CCS->musich->playMusic(musicBase::loseCombat); CCS->musich->playMusic("Music/LoseCombat", false);
CCS->videoh->open(VIDEO_LOSE_BATTLE_START); CCS->videoh->open(VIDEO_LOSE_BATTLE_START);
new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[311]); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[311]);
break; break;
} }
case 1: //flee case 1: //flee
{ {
CCS->musich->playMusic(musicBase::retreatBattle); CCS->musich->playMusic("Music/Retreat Battle", false);
CCS->videoh->open(VIDEO_RETREAT_START); CCS->videoh->open(VIDEO_RETREAT_START);
new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[310]); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[310]);
break; break;
} }
case 2: //surrender case 2: //surrender
{ {
CCS->musich->playMusic(musicBase::surrenderBattle); CCS->musich->playMusic("Music/Surrender Battle", false);
CCS->videoh->open(VIDEO_SURRENDER); CCS->videoh->open(VIDEO_SURRENDER);
new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[309]); new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[309]);
break; break;

View File

@ -987,7 +987,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
auto pos = sel->visitablePos(); auto pos = sel->visitablePos();
auto tile = LOCPLINT->cb->getTile(pos); auto tile = LOCPLINT->cb->getTile(pos);
if(tile) if(tile)
CCS->musich->playMusic(CCS->musich->terrainMusics[tile->tertype], -1); CCS->musich->playMusicFromSet("terrain", tile->tertype, true);
} }
if(centerView) if(centerView)
centerOn(sel); centerOn(sel);
@ -1487,7 +1487,7 @@ const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *ob
void CAdvMapInt::aiTurnStarted() void CAdvMapInt::aiTurnStarted()
{ {
adjustActiveness(true); adjustActiveness(true);
CCS->musich->playMusicFromSet(CCS->musich->aiMusics); CCS->musich->playMusicFromSet("enemy-turn", true);
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

@ -2,6 +2,7 @@
#include <SDL_image.h> #include <SDL_image.h>
#include "../lib/Filesystem/CResourceLoader.h" #include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/Filesystem/ISimpleResourceLoader.h"
#include "../lib/JsonNode.h" #include "../lib/JsonNode.h"
#include "../lib/vcmi_endian.h" #include "../lib/vcmi_endian.h"
@ -934,9 +935,16 @@ void CAnimation::init(CDefFile * file)
source[mapIt->first].resize(mapIt->second); source[mapIt->first].resize(mapIt->second);
} }
if (CResourceHandler::get()->existsResource(ResourceID(std::string("SPRITES/") + name, EResType::TEXT))) auto & configList = CResourceHandler::get()->getResourcesWithName(
ResourceID(std::string("SPRITES/") + name, EResType::TEXT));
BOOST_FOREACH(auto & entry, configList)
{ {
const JsonNode config(ResourceID(std::string("SPRITES/") + name, EResType::TEXT)); auto stream = entry.getLoader()->load(entry.getResourceName());
std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
stream->read(textData.get(), stream->getSize());
const JsonNode config((char*)textData.get(), stream->getSize());
std::string basepath; std::string basepath;
basepath = config["basepath"].String(); basepath = config["basepath"].String();

View File

@ -76,7 +76,16 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
} }
else else
{ {
ret = CSDL_Ext::createSurfaceWithBpp<3>(width, height); #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
int bmask = 0xff0000;
int gmask = 0x00ff00;
int rmask = 0x0000ff;
#else
int bmask = 0x0000ff;
int gmask = 0x00ff00;
int rmask = 0xff0000;
#endif
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0);
//it == 0xC; //it == 0xC;
for (int i=0; i<height; i++) for (int i=0; i<height; i++)
@ -127,7 +136,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
ret = IMG_LoadTyped_RW( ret = IMG_LoadTyped_RW(
//create SDL_RW with our data (will be deleted by SDL) //create SDL_RW with our data (will be deleted by SDL)
SDL_RWFromConstMem((void*)readFile.first.release(), readFile.second), SDL_RWFromConstMem((void*)readFile.first.get(), readFile.second),
1, // mark it for auto-deleting 1, // mark it for auto-deleting
&info.getExtension()[0] + 1); //pass extension without dot (+1 character) &info.getExtension()[0] + 1); //pass extension without dot (+1 character)

View File

@ -951,7 +951,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
townlist->onSelect = boost::bind(&CCastleInterface::townChange, this); townlist->onSelect = boost::bind(&CCastleInterface::townChange, this);
recreateIcons(); recreateIcons();
CCS->musich->playMusic(CCS->musich->townMusics[town->subID], -1); CCS->musich->playMusicFromSet("town-theme", town->subID, true);
bicons = CDefHandler::giveDefEss(graphics->buildingPics[town->subID]); bicons = CDefHandler::giveDefEss(graphics->buildingPics[town->subID]);
} }

View File

@ -1,90 +0,0 @@
#pragma once
/*
* CMusicBase.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
*
*/
// Use some magic to keep the list of files and their code name in sync.
// FIXME: first half of this list should be read from campmusic.txt
#define VCMI_MUSIC_LIST \
VCMI_MUSIC_ID(campainMusic01) VCMI_MUSIC_FILE("CampainMusic01.mp3") \
VCMI_MUSIC_ID(campainMusic02) VCMI_MUSIC_FILE("CampainMusic02.mp3") \
VCMI_MUSIC_ID(campainMusic03) VCMI_MUSIC_FILE("CampainMusic03.mp3") \
VCMI_MUSIC_ID(campainMusic04) VCMI_MUSIC_FILE("CampainMusic04.mp3") \
VCMI_MUSIC_ID(campainMusic05) VCMI_MUSIC_FILE("CampainMusic05.mp3") \
VCMI_MUSIC_ID(campainMusic06) VCMI_MUSIC_FILE("CampainMusic06.mp3") \
VCMI_MUSIC_ID(campainMusic07) VCMI_MUSIC_FILE("CampainMusic07.mp3") \
VCMI_MUSIC_ID(campainMusic08) VCMI_MUSIC_FILE("CampainMusic08.mp3") \
VCMI_MUSIC_ID(campainMusic09) VCMI_MUSIC_FILE("CampainMusic09.mp3") \
VCMI_MUSIC_ID(AITheme0) VCMI_MUSIC_FILE("AITheme0.mp3") \
VCMI_MUSIC_ID(AITheme1) VCMI_MUSIC_FILE("AITHEME1.MP3") \
VCMI_MUSIC_ID(AITheme2) VCMI_MUSIC_FILE("AITHEME2.MP3") \
VCMI_MUSIC_ID(combat1) VCMI_MUSIC_FILE("COMBAT01.MP3") \
VCMI_MUSIC_ID(combat2) VCMI_MUSIC_FILE("COMBAT02.MP3") \
VCMI_MUSIC_ID(combat3) VCMI_MUSIC_FILE("COMBAT03.MP3") \
VCMI_MUSIC_ID(combat4) VCMI_MUSIC_FILE("COMBAT04.MP3") \
VCMI_MUSIC_ID(castleTown) VCMI_MUSIC_FILE("CstleTown.mp3") \
VCMI_MUSIC_ID(towerTown) VCMI_MUSIC_FILE("TowerTown.mp3") \
VCMI_MUSIC_ID(rampartTown) VCMI_MUSIC_FILE("RAMPART.MP3") \
VCMI_MUSIC_ID(infernoTown) VCMI_MUSIC_FILE("InfernoTown.mp3") \
VCMI_MUSIC_ID(necroTown) VCMI_MUSIC_FILE("necroTown.mp3") \
VCMI_MUSIC_ID(dungeonTown) VCMI_MUSIC_FILE("DUNGEON.MP3") \
VCMI_MUSIC_ID(strongHoldTown) VCMI_MUSIC_FILE("StrongHold.mp3") \
VCMI_MUSIC_ID(fortressTown) VCMI_MUSIC_FILE("FortressTown.mp3") \
VCMI_MUSIC_ID(elemTown) VCMI_MUSIC_FILE("ElemTown.mp3") \
VCMI_MUSIC_ID(dirt) VCMI_MUSIC_FILE("DIRT.MP3") \
VCMI_MUSIC_ID(sand) VCMI_MUSIC_FILE("SAND.MP3") \
VCMI_MUSIC_ID(grass) VCMI_MUSIC_FILE("GRASS.MP3") \
VCMI_MUSIC_ID(snow) VCMI_MUSIC_FILE("SNOW.MP3") \
VCMI_MUSIC_ID(swamp) VCMI_MUSIC_FILE("SWAMP.MP3") \
VCMI_MUSIC_ID(rough) VCMI_MUSIC_FILE("ROUGH.MP3") \
VCMI_MUSIC_ID(underground) VCMI_MUSIC_FILE("Underground.mp3") \
VCMI_MUSIC_ID(lava) VCMI_MUSIC_FILE("LAVA.MP3") \
VCMI_MUSIC_ID(water) VCMI_MUSIC_FILE("WATER.MP3") \
VCMI_MUSIC_ID(goodTheme) VCMI_MUSIC_FILE("GoodTheme.mp3") \
VCMI_MUSIC_ID(neutralTheme) VCMI_MUSIC_FILE("NeutralTheme.mp3") \
VCMI_MUSIC_ID(evilTheme) VCMI_MUSIC_FILE("EvilTheme.mp3") \
VCMI_MUSIC_ID(secretTheme) VCMI_MUSIC_FILE("SecretTheme.mp3") \
VCMI_MUSIC_ID(loopLepr) VCMI_MUSIC_FILE("LoopLepr.mp3") \
VCMI_MUSIC_ID(mainMenu) VCMI_MUSIC_FILE("MAINMENU.MP3") \
VCMI_MUSIC_ID(winScenario) VCMI_MUSIC_FILE("Win Scenario.mp3" ) \
VCMI_MUSIC_ID(campainMusic10) VCMI_MUSIC_FILE("CampainMusic10.mp3") \
VCMI_MUSIC_ID(bladeABcampaign) VCMI_MUSIC_FILE("BladeABCampaign.mp3") \
VCMI_MUSIC_ID(bladeDBcampaign) VCMI_MUSIC_FILE("BladeDBCampaign.mp3") \
VCMI_MUSIC_ID(bladeDScampaign) VCMI_MUSIC_FILE("BladeDSCampaign.mp3") \
VCMI_MUSIC_ID(bladeFLcampaign) VCMI_MUSIC_FILE("BladeFLCampaign.mp3") \
VCMI_MUSIC_ID(bladeFWcampaign) VCMI_MUSIC_FILE("BladeFWCampaign.mp3") \
VCMI_MUSIC_ID(bladePWcampaign) VCMI_MUSIC_FILE("BladePFCampaign.mp3") \
VCMI_MUSIC_ID(campainMusic11) VCMI_MUSIC_FILE("CampainMusic11.mp3") \
VCMI_MUSIC_ID(loseCampain) VCMI_MUSIC_FILE("Lose Campain.mp3") \
VCMI_MUSIC_ID(loseCastle) VCMI_MUSIC_FILE("LoseCastle.mp3") \
VCMI_MUSIC_ID(loseCombat) VCMI_MUSIC_FILE("LoseCombat.mp3") \
VCMI_MUSIC_ID(mainMenuWoG) VCMI_MUSIC_FILE("MainMenuWoG.mp3") \
VCMI_MUSIC_ID(retreatBattle) VCMI_MUSIC_FILE("Retreat Battle.mp3") \
VCMI_MUSIC_ID(surrenderBattle) VCMI_MUSIC_FILE("Surrender Battle.mp3") \
VCMI_MUSIC_ID(ultimateLose) VCMI_MUSIC_FILE("UltimateLose.mp3") \
VCMI_MUSIC_ID(winBattle) VCMI_MUSIC_FILE("Win Battle.mp3") \
VCMI_MUSIC_ID(defendCastle) VCMI_MUSIC_FILE("Defend Castle.mp3") \
class musicBase
{
public:
// Make a list of enums
#define VCMI_MUSIC_ID(x) x,
#define VCMI_MUSIC_FILE(y)
enum musicID {
music_todo=0, // temp entry until code is fixed
VCMI_MUSIC_LIST
};
#undef VCMI_MUSIC_ID
#undef VCMI_MUSIC_FILE
};

View File

@ -53,7 +53,7 @@ void CAudioBase::init()
void CAudioBase::release() void CAudioBase::release()
{ {
if (initialized) if (initialized)
{ {
Mix_CloseAudio(); Mix_CloseAudio();
initialized = false; initialized = false;
} }
@ -332,40 +332,27 @@ CMusicHandler::CMusicHandler():
{ {
listener(boost::bind(&CMusicHandler::onVolumeChange, this, _1)); listener(boost::bind(&CMusicHandler::onVolumeChange, this, _1));
// Map music IDs // Map music IDs
#ifdef CPP11_USE_INITIALIZERS_LIST
#define VCMI_MUSIC_ID(x) { musicBase::x ,
#define VCMI_MUSIC_FILE(y) y },
musics = { VCMI_MUSIC_LIST};
#undef VCMI_MUSIC_NAME
#undef VCMI_MUSIC_FILE
#else
#define VCMI_MUSIC_ID(x) ( musicBase::x ,
#define VCMI_MUSIC_FILE(y) y )
musics = map_list_of
VCMI_MUSIC_LIST;
#undef VCMI_MUSIC_NAME
#undef VCMI_MUSIC_FILE
#endif
// Vectors for helper // Vectors for helper
aiMusics += musicBase::AITheme0, musicBase::AITheme1, musicBase::AITheme2; const std::string setEnemy[] = {"AITheme0", "AITheme1", "AITheme2"};
const std::string setBattle[] = {"Combat01", "Combat02", "Combat03", "Combat04"};
const std::string setTerrain[] = {"Dirt", "Sand", "Grass", "Snow", "Swamp", "Rough", "Underground", "Lava", "Water"};
const std::string setTowns[] = {"CstleTown", "Rampart", "TowerTown", "InfernoTown",
"NecroTown", "Dungeon", "Stronghold", "FortressTown", "ElemTown"};
battleMusics += musicBase::combat1, musicBase::combat2, auto fillSet = [=](std::string setName, const std::string list[], size_t amount)
musicBase::combat3, musicBase::combat4; {
for (size_t i=0; i < amount; i++)
addEntryToSet(setName, i, std::string("music/") + list[i]);
};
fillSet("enemy-turn", setEnemy, ARRAY_COUNT(setEnemy));
fillSet("battle", setBattle, ARRAY_COUNT(setBattle));
fillSet("terrain", setTerrain, ARRAY_COUNT(setTerrain));
fillSet("town-theme", setTowns, ARRAY_COUNT(setTowns));
}
townMusics += musicBase::castleTown, musicBase::rampartTown, void CMusicHandler::addEntryToSet(std::string set, int musicID, std::string musicURI)
musicBase::towerTown, musicBase::infernoTown, {
musicBase::necroTown, musicBase::dungeonTown, musicsSet[set][musicID] = musicURI;
musicBase::strongHoldTown, musicBase::fortressTown,
musicBase::elemTown;
terrainMusics += musicBase::dirt, musicBase::sand, musicBase::grass,
musicBase::snow, musicBase::swamp, musicBase::rough,
musicBase::underground, musicBase::lava,musicBase::water;
} }
void CMusicHandler::init() void CMusicHandler::init()
@ -391,23 +378,46 @@ void CMusicHandler::release()
CAudioBase::release(); CAudioBase::release();
} }
// Plays a music void CMusicHandler::playMusic(std::string musicURI, bool loop)
// loop: -1 always repeats, 0=do not play, 1+=number of loops
void CMusicHandler::playMusic(musicBase::musicID musicID, int loop)
{ {
if (current.get() != NULL && *current == musicID) if (current && current->isTrack( musicURI))
return; return;
queueNext(new MusicEntry(this, musicID, loop)); queueNext(new MusicEntry(this, "", musicURI, loop));
} }
// Helper. Randomly plays tracks from music_vec void CMusicHandler::playMusicFromSet(std::string whichSet, bool loop)
void CMusicHandler::playMusicFromSet(std::vector<musicBase::musicID> &music_vec, int loop)
{ {
if (current.get() != NULL && *current == music_vec) auto selectedSet = musicsSet.find(whichSet);
if (selectedSet == musicsSet.end())
{
tlog0 << "Error: playing music from non-existing set: " << whichSet << "\n";
return;
}
if (current && current->isSet(whichSet))
return; return;
queueNext(new MusicEntry(this, music_vec, loop)); queueNext(new MusicEntry(this, whichSet, "", loop));
}
void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loop)
{
auto selectedSet = musicsSet.find(whichSet);
if (selectedSet == musicsSet.end())
{
tlog0 << "Error: playing music from non-existing set: " << whichSet << "\n";
return;
}
auto selectedEntry = selectedSet->second.find(entryID);
if (selectedEntry == selectedSet->second.end())
{
tlog0 << "Error: playing non-existing entry " << entryID << " from set: " << whichSet << "\n";
return;
}
queueNext(new MusicEntry(this, "", selectedEntry->second, loop));
} }
void CMusicHandler::queueNext(MusicEntry *queued) void CMusicHandler::queueNext(MusicEntry *queued)
@ -430,7 +440,6 @@ void CMusicHandler::queueNext(MusicEntry *queued)
} }
} }
// Stop and free the current music
void CMusicHandler::stopMusic(int fade_ms) void CMusicHandler::stopMusic(int fade_ms)
{ {
if (!initialized) if (!initialized)
@ -441,10 +450,8 @@ void CMusicHandler::stopMusic(int fade_ms)
if (current.get() != NULL) if (current.get() != NULL)
current->stop(fade_ms); current->stop(fade_ms);
next.reset(); next.reset();
} }
// Sets the music volume, from 0 (mute) to 100
void CMusicHandler::setVolume(ui32 percent) void CMusicHandler::setVolume(ui32 percent)
{ {
CAudioBase::setVolume(percent); CAudioBase::setVolume(percent);
@ -453,7 +460,6 @@ void CMusicHandler::setVolume(ui32 percent)
Mix_VolumeMusic((MIX_MAX_VOLUME * volume)/100); Mix_VolumeMusic((MIX_MAX_VOLUME * volume)/100);
} }
// Called by SDL when a music finished.
void CMusicHandler::musicFinishedCallback(void) void CMusicHandler::musicFinishedCallback(void)
{ {
boost::mutex::scoped_lock guard(musicMutex); boost::mutex::scoped_lock guard(musicMutex);
@ -474,50 +480,39 @@ void CMusicHandler::musicFinishedCallback(void)
} }
} }
MusicEntry::MusicEntry(CMusicHandler *_owner, musicBase::musicID _musicID, int _loopCount): MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
owner(_owner), owner(owner),
music(NULL), music(nullptr),
loopCount(_loopCount) looped(looped),
setName(setName)
{ {
load(_musicID); if (!musicURI.empty())
load(musicURI);
} }
MusicEntry::MusicEntry(CMusicHandler *_owner, std::vector<musicBase::musicID> &_musicVec, int _loopCount):
currentID(musicBase::music_todo),
owner(_owner),
music(NULL),
loopCount(_loopCount),
musicVec(_musicVec)
{
//In this case music will be loaded only on playing - no need to call load() here
}
MusicEntry::~MusicEntry() MusicEntry::~MusicEntry()
{ {
tlog5<<"Del-ing music file "<<filename<<"\n"; tlog5<<"Del-ing music file "<<currentName<<"\n";
if (music) if (music)
Mix_FreeMusic(music); Mix_FreeMusic(music);
} }
void MusicEntry::load(musicBase::musicID ID) void MusicEntry::load(std::string musicURI)
{ {
if (music) if (music)
{ {
tlog5<<"Del-ing music file "<<filename<<"\n"; tlog5<<"Del-ing music file "<<currentName<<"\n";
Mix_FreeMusic(music); Mix_FreeMusic(music);
} }
currentID = ID; currentName = musicURI;
filename = GameConstants::DATA_DIR + "/Mp3/";
filename += owner->musics[ID];
tlog5<<"Loading music file "<<filename<<"\n"; tlog5<<"Loading music file "<<musicURI<<"\n";
music = Mix_LoadMUS(filename.c_str()); music = Mix_LoadMUS(CResourceHandler::get()->getResourceName(ResourceID(musicURI, EResType::MUSIC)).c_str());
if(!music) if(!music)
{ {
tlog3 << "Warning: Cannot open " << filename << ": " << Mix_GetError() << std::endl; tlog3 << "Warning: Cannot open " << currentName << ": " << Mix_GetError() << std::endl;
return; return;
} }
@ -529,16 +524,19 @@ void MusicEntry::load(musicBase::musicID ID)
bool MusicEntry::play() bool MusicEntry::play()
{ {
if (loopCount == 0) if (!looped && music) //already played once - return
return false; return false;
if (loopCount > 0) if (!setName.empty())
loopCount--; {
auto set = owner->musicsSet[setName];
size_t entryID = rand() % set.size();
auto iterator = set.begin();
std::advance(iterator, entryID);
load(iterator->second);
}
if (!musicVec.empty()) tlog5<<"Playing music file "<<currentName<<"\n";
load(musicVec.at(rand() % musicVec.size()));
tlog5<<"Playing music file "<<filename<<"\n";
if(Mix_PlayMusic(music, 1) == -1) if(Mix_PlayMusic(music, 1) == -1)
{ {
tlog1 << "Unable to play music (" << Mix_GetError() << ")" << std::endl; tlog1 << "Unable to play music (" << Mix_GetError() << ")" << std::endl;
@ -549,17 +547,17 @@ bool MusicEntry::play()
void MusicEntry::stop(int fade_ms) void MusicEntry::stop(int fade_ms)
{ {
tlog5<<"Stoping music file "<<filename<<"\n"; tlog5<<"Stoping music file "<<currentName<<"\n";
loopCount = 0; looped = false;
Mix_FadeOutMusic(fade_ms); Mix_FadeOutMusic(fade_ms);
} }
bool MusicEntry::operator == (musicBase::musicID _musicID) const bool MusicEntry::isSet(std::string set)
{ {
return musicVec.empty() && currentID == _musicID; return !setName.empty() && set == setName;
} }
bool MusicEntry::operator == (std::vector<musicBase::musicID> &_musicVec) const bool MusicEntry::isTrack(std::string track)
{ {
return musicVec == _musicVec; return setName.empty() && track == currentName;
} }

View File

@ -2,7 +2,6 @@
#include "CConfigHandler.h" #include "CConfigHandler.h"
#include "CSoundBase.h" #include "CSoundBase.h"
#include "CMusicBase.h"
#include "../lib/CCreatureHandler.h" #include "../lib/CCreatureHandler.h"
#include "CSndHandler.h" #include "CSndHandler.h"
@ -113,22 +112,21 @@ class CMusicHandler;
//Class for handling one music file //Class for handling one music file
class MusicEntry class MusicEntry
{ {
std::string filename; //used only for debugging and console messages
musicBase::musicID currentID;
CMusicHandler *owner; CMusicHandler *owner;
Mix_Music *music; Mix_Music *music;
int loopCount; bool looped;
//if not empty - vector from which music will be randomly selected //if not null - set from which music will be randomly selected
std::vector<musicBase::musicID> musicVec; std::string setName;
std::string currentName;
void load(musicBase::musicID);
void load(std::string musicURI);
public: public:
bool operator == (musicBase::musicID musicID) const; bool isSet(std::string setName);
bool operator == (std::vector<musicBase::musicID> &_musicVec) const; bool isTrack(std::string trackName);
MusicEntry(CMusicHandler *owner, musicBase::musicID musicID, int _loopCount); MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
MusicEntry(CMusicHandler *owner, std::vector<musicBase::musicID> &_musicVec, int _loopCount);
~MusicEntry(); ~MusicEntry();
bool play(); bool play();
@ -149,22 +147,26 @@ private:
unique_ptr<MusicEntry> next; unique_ptr<MusicEntry> next;
void queueNext(MusicEntry *queued); void queueNext(MusicEntry *queued);
std::map<std::string, std::map<int, std::string> > musicsSet;
public: public:
CMusicHandler(); CMusicHandler();
/// add entry with URI musicURI in set. Track will have ID musicID
void addEntryToSet(std::string set, int musicID, std::string musicURI);
void init(); void init();
void release(); void release();
void setVolume(ui32 percent); void setVolume(ui32 percent);
// Musics /// play track by URI, if loop = true music will be looped
std::map<musicBase::musicID, std::string> musics; void playMusic(std::string musicURI, bool loop);
std::vector<musicBase::musicID> aiMusics; /// play random track from this set
std::vector<musicBase::musicID> battleMusics; void playMusicFromSet(std::string musicSet, bool loop);
std::vector<musicBase::musicID> townMusics; /// play specific track from set
std::vector<musicBase::musicID> terrainMusics; void playMusicFromSet(std::string musicSet, int entryID, bool loop);
void playMusic(musicBase::musicID musicID, int loop=1);
void playMusicFromSet(std::vector<musicBase::musicID> &music_vec, int loop=1);
void stopMusic(int fade_ms=1000); void stopMusic(int fade_ms=1000);
void musicFinishedCallback(void); void musicFinishedCallback(void);
friend class MusicEntry;
}; };

View File

@ -256,7 +256,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
if(makingTurn && ho->tempOwner == playerID) //we are moving our hero - we may need to update assigned path if(makingTurn && ho->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
{ {
//We may need to change music - select new track, music handler will change it if needed //We may need to change music - select new track, music handler will change it if needed
CCS->musich->playMusic(CCS->musich->terrainMusics[LOCPLINT->cb->getTile(ho->visitablePos())->tertype], -1); CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(ho->visitablePos())->tertype, true);
if(details.result == TryMoveHero::TELEPORTATION) if(details.result == TryMoveHero::TELEPORTATION)
{ {

View File

@ -259,7 +259,7 @@ void CMenuScreen::show(SDL_Surface * to)
void CMenuScreen::activate() void CMenuScreen::activate()
{ {
CCS->musich->playMusic(musicBase::mainMenu, -1); CCS->musich->playMusic("Music/MainMenu", true);
if (!config["video"].isNull()) if (!config["video"].isNull())
CCS->videoh->open(config["video"]["name"].String()); CCS->videoh->open(config["video"]["name"].String());
CIntObject::activate(); CIntObject::activate();
@ -567,13 +567,15 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti
else if(Type == CMenuScreen::campaignList) else if(Type == CMenuScreen::campaignList)
{ {
bordered = false; bordered = false;
bg = new CPicture(BitmapHandler::loadBitmap("CamCust.bmp"), 0, 0, true); bg = new CPicture("CamCust.bmp", 0, 0);
pos = bg->center(); pos = bg->center();
} }
else else
{ {
bordered = true; bordered = true;
bg = new CPicture(BitmapHandler::loadBitmap(rand()%2 ? "ZPIC1000.bmp" : "ZPIC1001.bmp"), 0, 0, true); //load random background
const JsonVector & bgNames = (*CGP->pregameConfig)["game-select"].Vector();
bg = new CPicture(bgNames[rand() % bgNames.size()].String(), 0, 0);
pos = bg->center(); pos = bg->center();
} }

View File

@ -489,14 +489,14 @@ public:
/// Handles background screen, loads graphics for victory/loss condition and random town or hero selection /// Handles background screen, loads graphics for victory/loss condition and random town or hero selection
class CGPreGame : public CIntObject, public IUpdateable class CGPreGame : public CIntObject, public IUpdateable
{ {
const JsonNode * const pregameConfig;
void loadGraphics(); void loadGraphics();
void disposeGraphics(); void disposeGraphics();
CGPreGame(); //Use createIfNotPresent CGPreGame(); //Use createIfNotPresent
public: public:
const JsonNode * const pregameConfig;
CMenuScreen* menu; CMenuScreen* menu;
SDL_Surface *nHero, *rHero, *nTown, *rTown; // none/random hero/town imgs SDL_Surface *nHero, *rHero, *nTown, *rTown; // none/random hero/town imgs

View File

@ -431,15 +431,27 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg, const CStackInstance * Creature) CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg, const CStackInstance * Creature)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL;
addUsedEvents(LCLICK | RCLICK | HOVER); addUsedEvents(LCLICK | RCLICK | HOVER);
pos.x += x;
pos.y += y;
owner = Owner;
//assert(Creature == CGI->creh->creatures[Creature->idNumber]); //assert(Creature == CGI->creh->creatures[Creature->idNumber]);
upg = Upg; upg = Upg;
ID = IID; ID = IID;
myStack = Creature; myStack = Creature;
creature = Creature ? Creature->type : NULL; creature = Creature ? Creature->type : NULL;
if (creature)
{
std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT";
creatureImage = new CAnimImage(imgName, creature->idNumber + 2);
}
else
creatureImage = nullptr;
count = Creature ? Creature->count : 0; count = Creature ? Creature->count : 0;
pos.x += x;
pos.y += y;
if(Owner->smallIcons) if(Owner->smallIcons)
{ {
pos.w = 32; pos.w = 32;
@ -450,7 +462,6 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg
pos.w = 58; pos.w = 58;
pos.h = 64; pos.h = 64;
} }
owner = Owner;
} }
void CGarrisonSlot::showAll(SDL_Surface * to) void CGarrisonSlot::showAll(SDL_Surface * to)
@ -458,9 +469,9 @@ void CGarrisonSlot::showAll(SDL_Surface * to)
std::map<int,SDL_Surface*> &imgs = (owner->smallIcons ? graphics->smallImgs : graphics->bigImgs); std::map<int,SDL_Surface*> &imgs = (owner->smallIcons ? graphics->smallImgs : graphics->bigImgs);
if(creature) if(creature)
{ {
creatureImage->showAll(to);
char buf[15]; char buf[15];
SDL_itoa(count,buf,10); SDL_itoa(count,buf,10);
blitAt(imgs[creature->idNumber],pos,to);
printTo(buf, pos.x+pos.w, pos.y+pos.h+1, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, Colors::Cornsilk, to); printTo(buf, pos.x+pos.w, pos.y+pos.h+1, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, Colors::Cornsilk, to);
if((owner->highlighted==this) if((owner->highlighted==this)
@ -476,12 +487,6 @@ void CGarrisonSlot::showAll(SDL_Surface * to)
} }
} }
CGarrisonInt::~CGarrisonInt()
{/*
for(size_t i = 0; i<splitButtons.size(); i++)
delete splitButtons[i];*/
}
void CGarrisonInt::addSplitBtn(CAdventureMapButton * button) void CGarrisonInt::addSplitBtn(CAdventureMapButton * button)
{ {
addChild(button); addChild(button);

View File

@ -306,7 +306,6 @@ class CGarrisonInt;
/// A single garrison slot which holds one creature of a specific amount /// A single garrison slot which holds one creature of a specific amount
class CGarrisonSlot : public CIntObject class CGarrisonSlot : public CIntObject
{ {
public:
int ID; //for identification int ID; //for identification
CGarrisonInt *owner; CGarrisonInt *owner;
const CStackInstance *myStack; //NULL if slot is empty const CStackInstance *myStack; //NULL if slot is empty
@ -315,6 +314,8 @@ public:
int upg; //0 - up garrison, 1 - down garrison int upg; //0 - up garrison, 1 - down garrison
bool highlight; bool highlight;
CAnimImage * creatureImage;
public:
virtual void hover (bool on); //call-in virtual void hover (bool on); //call-in
const CArmedInstance * getObj(); const CArmedInstance * getObj();
bool our(); bool our();
@ -322,6 +323,8 @@ public:
void clickLeft(tribool down, bool previousState); void clickLeft(tribool down, bool previousState);
void showAll(SDL_Surface * to); void showAll(SDL_Surface * to);
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CStackInstance * Creature=NULL); CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CStackInstance * Creature=NULL);
friend class CGarrisonInt;
}; };
/// Class which manages slots of upper and lower garrison, splitting of units /// Class which manages slots of upper and lower garrison, splitting of units
@ -367,7 +370,6 @@ public:
//smallImgs - units images size 64x58 or 32x32; //smallImgs - units images size 64x58 or 32x32;
//twoRows - display slots in 2 row (1st row = 4 slots, 2nd = 3 slots) //twoRows - display slots in 2 row (1st row = 4 slots, 2nd = 3 slots)
CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor
~CGarrisonInt(); //d-tor
}; };
/// draws picture with creature on background, use Animated=true to get animation /// draws picture with creature on background, use Animated=true to get animation

View File

@ -64,8 +64,7 @@ void Graphics::loadPaletteAndColors()
neutralColorPalette = new SDL_Color[32]; neutralColorPalette = new SDL_Color[32];
std::ifstream ncp; std::ifstream ncp;
std::string neutralFile = GameConstants::DATA_DIR + "/config/NEUTRAL.PAL"; ncp.open(CResourceHandler::get()->getResourceName(ResourceID("config/NEUTRAL.PAL")), std::ios::binary);
ncp.open(neutralFile.c_str(), std::ios::binary);
for(int i=0; i<32; ++i) for(int i=0; i<32; ++i)
{ {
ncp.read((char*)&neutralColorPalette[i].r,1); ncp.read((char*)&neutralColorPalette[i].r,1);

View File

@ -1303,7 +1303,6 @@ void CBoundedLabel::recalculateLines(const std::string &Txt)
const Font &f = *graphics->fonts[font]; const Font &f = *graphics->fonts[font];
int lineHeight = f.height; int lineHeight = f.height;
int lineCapacity = pos.h / lineHeight;
lines = CMessage::breakText(Txt, pos.w, font); lines = CMessage::breakText(Txt, pos.w, font);

View File

@ -45,7 +45,7 @@ SDL_Surface * CSDL_Ext::copySurface(SDL_Surface * mod) //returns copy of given s
template<int bpp> template<int bpp>
SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height) SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
{ {
int rMask = 0, gMask = 0, bMask = 0, aMask = 0; Uint32 rMask = 0, gMask = 0, bMask = 0, aMask = 0;
Channels::px<bpp>::r.set((Uint8*)&rMask, 255); Channels::px<bpp>::r.set((Uint8*)&rMask, 255);
Channels::px<bpp>::g.set((Uint8*)&gMask, 255); Channels::px<bpp>::g.set((Uint8*)&gMask, 255);

View File

@ -26,6 +26,7 @@
"SOUNDS/": "SOUNDS/":
[ [
{"type" : "file", "path" : "ALL/Data/H3ab_ahd.snd"}, {"type" : "file", "path" : "ALL/Data/H3ab_ahd.snd"},
{"type" : "file", "path" : "ALL/Data/Heroes3-cd2.snd"},
{"type" : "file", "path" : "ALL/Data/Heroes3.snd"}, {"type" : "file", "path" : "ALL/Data/Heroes3.snd"},
//WoG have overriden sounds with .82m extension in Data //WoG have overriden sounds with .82m extension in Data
{"type" : "dir", "path" : "GLOBAL/Data"}, {"type" : "dir", "path" : "GLOBAL/Data"},

View File

@ -1,4 +1,6 @@
{ {
//images used in game selection screen
"game-select" : ["ZPIC1000", "ZPIC1001"],
//Main menu window, consists of several sub-menus aka items //Main menu window, consists of several sub-menus aka items
"window": "window":
{ {
@ -68,7 +70,7 @@
{ "x":90, "y":72, "file":"DATA/GOOD1.H3C", "image":"CAMPGD1S", "video":"CGOOD1", "open": true }, { "x":90, "y":72, "file":"DATA/GOOD1.H3C", "image":"CAMPGD1S", "video":"CGOOD1", "open": true },
{ "x":539, "y":72, "file":"DATA/EVIL1.H3C", "image":"CAMPEV1S", "video":"CEVIL1", "open": true }, { "x":539, "y":72, "file":"DATA/EVIL1.H3C", "image":"CAMPEV1S", "video":"CEVIL1", "open": true },
{ "x":43, "y":245, "file":"DATA/GOOD2.H3C", "image":"CAMPGD2S", "video":"CGOOD2", "open": true }, { "x":43, "y":245, "file":"DATA/GOOD2.H3C", "image":"CAMPGD2S", "video":"CGOOD2", "open": true },
{ "x":313, "y":244, "file":"DATA/NEUTRAL.H3C", "image":"CAMPNEUS", "video":"CNEUTRAL", "open": true }, { "x":313, "y":244, "file":"DATA/NEUTRAL1.H3C", "image":"CAMPNEUS", "video":"CNEUTRAL", "open": true },
{ "x":586, "y":246, "file":"DATA/EVIL2.H3C", "image":"CAMPEV2S", "video":"CEVIL2", "open": true }, { "x":586, "y":246, "file":"DATA/EVIL2.H3C", "image":"CAMPEV2S", "video":"CEVIL2", "open": true },
{ "x":34, "y":417, "file":"DATA/GOOD3.H3C", "image":"CAMPGD3S", "video":"CGOOD3", "open": true }, { "x":34, "y":417, "file":"DATA/GOOD3.H3C", "image":"CAMPGD3S", "video":"CGOOD3", "open": true },
{ "x":404, "y":414, "file":"DATA/SECRET.H3C", "image":"CAMPSCTS", "video":"CSECRET", "open": true } { "x":404, "y":414, "file":"DATA/SECRET.H3C", "image":"CAMPSCTS", "video":"CSECRET", "open": true }

View File

@ -560,8 +560,7 @@ void CGeneralTextHandler::load()
zcrexp.push_back(nameBuf); zcrexp.push_back(nameBuf);
} }
std::string threatLevelDir = GameConstants::DATA_DIR + "/config/threatlevel.txt"; std::ifstream ifs(CResourceHandler::get()->getResourceName(ResourceID("config/threatlevel.txt")), std::ios::binary);
std::ifstream ifs(threatLevelDir.c_str(), std::ios::in | std::ios::binary);
getline(ifs, buf); //skip 1st line getline(ifs, buf); //skip 1st line
for (int i = 0; i < 13; ++i) for (int i = 0; i < 13; ++i)
{ {

View File

@ -118,6 +118,17 @@ ResourceLocator CResourceLoader::getResource(const ResourceID & resourceIdent) c
return resource->second.back(); return resource->second.back();
} }
const std::list<ResourceLocator> & CResourceLoader::getResourcesWithName(const ResourceID & resourceIdent) const
{
static const std::list<ResourceLocator> emptyList;
auto resource = resources.find(resourceIdent);
if (resource == resources.end())
return emptyList;
return resource->second;
}
std::string CResourceLoader::getResourceName(const ResourceID & resourceIdent) const std::string CResourceLoader::getResourceName(const ResourceID & resourceIdent) const
{ {
auto locator = getResource(resourceIdent); auto locator = getResource(resourceIdent);
@ -147,6 +158,11 @@ void CResourceLoader::addLoader(std::string mountPoint, ISimpleResourceLoader *
// Create identifier and locator and add them to the resources list // Create identifier and locator and add them to the resources list
ResourceID ident(mountPoint, file.getStem(), file.getType()); ResourceID ident(mountPoint, file.getStem(), file.getType());
//check if entry can be directory. Will only work for filesystem loader but H3 archives don't have dirs anyway.
if (boost::filesystem::is_directory(loader->getOrigin() + '/' + entry))
ident.setType(EResType::DIRECTORY);
ResourceLocator locator(loader, entry); ResourceLocator locator(loader, entry);
resources[ident].push_back(locator); resources[ident].push_back(locator);
} }
@ -247,6 +263,7 @@ std::string EResTypeHelper::getEResTypeAsString(EResType::Type type)
MAP_ENUM(CLIENT_SAVEGAME) MAP_ENUM(CLIENT_SAVEGAME)
MAP_ENUM(LIB_SAVEGAME) MAP_ENUM(LIB_SAVEGAME)
MAP_ENUM(SERVER_SAVEGAME) MAP_ENUM(SERVER_SAVEGAME)
MAP_ENUM(DIRECTORY)
MAP_ENUM(OTHER); MAP_ENUM(OTHER);
#undef MAP_ENUM #undef MAP_ENUM
@ -279,17 +296,10 @@ void CResourceHandler::initialize()
//create "LOCAL" dir with current userDir (may be same as rootDir) //create "LOCAL" dir with current userDir (may be same as rootDir)
initialLoader->addLoader("LOCAL/", userDir); initialLoader->addLoader("LOCAL/", userDir);
//check for presence of "VCMI" mod. If found - add it to our initial FS
std::string filename = initialLoader->getResourceName(ResourceID("ALL/MODS/VCMI"));
if (!filename.empty())
initialLoader->addLoader("ALL/", new CFilesystemLoader(filename, 2));
} }
void CResourceHandler::loadFileSystem(const std::string fsConfigURI) void CResourceHandler::loadFileSystem(const std::string fsConfigURI)
{ {
//TODO: better way to detect fs config.
// right now it can be: global_dir/config/, local_dir/config, global/mods/vcmi/config, local/mods/vcmi/config
auto fsConfigData = initialLoader->loadData(ResourceID(fsConfigURI, EResType::TEXT)); auto fsConfigData = initialLoader->loadData(ResourceID(fsConfigURI, EResType::TEXT));
const JsonNode fsConfig((char*)fsConfigData.first.get(), fsConfigData.second); const JsonNode fsConfig((char*)fsConfigData.first.get(), fsConfigData.second);
@ -298,26 +308,26 @@ void CResourceHandler::loadFileSystem(const std::string fsConfigURI)
{ {
BOOST_FOREACH(auto & entry, mountPoint.second.Vector()) BOOST_FOREACH(auto & entry, mountPoint.second.Vector())
{ {
tlog5 << "loading resource at " << entry["path"].String() << ": "; tlog5 << "loading resource at " << entry["path"].String() << "\n";
std::string filename = initialLoader->getResourceName(ResourceID(entry["path"].String()));
if (!filename.empty()) if (entry["type"].String() == "dir")
{ {
if (entry["type"].String() == "dir") std::string filename = initialLoader->getResourceName(ResourceID(entry["path"].String(), EResType::DIRECTORY));
if (!filename.empty())
{ {
int depth = 16; int depth = 16;
if (!entry["depth"].isNull()) if (!entry["depth"].isNull())
depth = entry["depth"].Float(); depth = entry["depth"].Float();
resourceLoader->addLoader(mountPoint.first, new CFilesystemLoader(filename, depth)); resourceLoader->addLoader(mountPoint.first, new CFilesystemLoader(filename, depth));
} }
if (entry["type"].String() == "file")
resourceLoader->addLoader(mountPoint.first, new CLodArchiveLoader(filename));
tlog5 << "OK\n";
} }
else
tlog5 << "Not found\n"; if (entry["type"].String() == "file")
{
std::string filename = initialLoader->getResourceName(ResourceID(entry["path"].String(), EResType::ARCHIVE));
if (!filename.empty())
resourceLoader->addLoader(mountPoint.first, new CLodArchiveLoader(filename));
}
} }
} }
} }

View File

@ -53,6 +53,7 @@ namespace EResType
CLIENT_SAVEGAME, CLIENT_SAVEGAME,
LIB_SAVEGAME, LIB_SAVEGAME,
SERVER_SAVEGAME, SERVER_SAVEGAME,
DIRECTORY,
OTHER OTHER
}; };
} }
@ -259,9 +260,12 @@ public:
* @return resource locator for this resource or empty one if resource was not found * @return resource locator for this resource or empty one if resource was not found
*/ */
ResourceLocator getResource(const ResourceID & resourceIdent) const; ResourceLocator getResource(const ResourceID & resourceIdent) const;
/// returns ALL overriden resources with same name, including last one acessible via getResource
const std::list<ResourceLocator> & getResourcesWithName(const ResourceID & resourceIdent) const;
/// returns real name of file in filesystem. Not usable for archives /// returns real name of file in filesystem. Not usable for archives
std::string getResourceName(const ResourceID & resourceIdent) const; std::string getResourceName(const ResourceID & resourceIdent) const;
/// return size of file or 0 if not found
/** /**
* Get iterator for looping all files matching filter * Get iterator for looping all files matching filter