1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-28 23:06:24 +02:00

Moved creature sounds to CCreature. Sound IDs are now stored as strings.

Creature parser is complete (untested).
This commit is contained in:
DjWarmonger 2012-09-17 19:00:26 +00:00
parent 061ed69c63
commit 9438cfc7e2
5 changed files with 153 additions and 81 deletions

View File

@ -153,6 +153,25 @@ Mix_Chunk *CSoundHandler::GetSoundChunk(soundBase::soundID soundID)
}
}
Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound)
{
// Load and insert
try
{
auto data = CResourceHandler::get()->loadData(ResourceID(std::string("SOUNDS/") + sound, EResType::SOUND)); //TODO: allow other sound folders?
SDL_RWops *ops = SDL_RWFromMem(data.first.release(), data.second);
Mix_Chunk *chunk;
chunk = Mix_LoadWAV_RW(ops, 1); // will free ops
return chunk;
}
catch(std::exception &e)
{
tlog3 << "Cannot get sound " << sound << " chunk: " << e.what() << "\n";
return nullptr;
}
}
// Get a soundID given a filename
soundBase::soundID CSoundHandler::getSoundID(const std::string &fileName)
{
@ -167,46 +186,6 @@ soundBase::soundID CSoundHandler::getSoundID(const std::string &fileName)
void CSoundHandler::initCreaturesSounds(const std::vector<ConstTransitivePtr< CCreature> > &creatures)
{
tlog5 << "\t\tReading config/cr_sounds.json" << std::endl;
const JsonNode config(ResourceID("config/cr_sounds.json"));
CBattleSounds.resize(creatures.size());
if (!config["creature_sounds"].isNull()) {
BOOST_FOREACH(const JsonNode &node, config["creature_sounds"].Vector()) {
const JsonNode *value;
int id;
value = &node["name"];
bmap<std::string,int>::const_iterator i = CGI->creh->nameToID.find(value->String());
if (i != CGI->creh->nameToID.end())
id = i->second;
else
{
tlog1 << "Sound info for an unknown creature: " << value->String() << std::endl;
continue;
}
/* This is a bit ugly. Maybe we should use an array for
* sound ids instead of separate variables and define
* attack/defend/killed/... as indexes. */
#define GET_SOUND_VALUE(value_name) do { value = &node[#value_name]; if (!value->isNull()) CBattleSounds[id].value_name = getSoundID(value->String()); } while(0)
GET_SOUND_VALUE(attack);
GET_SOUND_VALUE(defend);
GET_SOUND_VALUE(killed);
GET_SOUND_VALUE(move);
GET_SOUND_VALUE(shoot);
GET_SOUND_VALUE(wince);
GET_SOUND_VALUE(ext1);
GET_SOUND_VALUE(ext2);
GET_SOUND_VALUE(startMoving);
GET_SOUND_VALUE(endMoving);
#undef GET_SOUND_VALUE
}
}
//commented to avoid spurious warnings
/*
@ -269,6 +248,30 @@ int CSoundHandler::playSound(soundBase::soundID soundID, int repeats)
return channel;
}
int CSoundHandler::playSound(std::string sound, int repeats)
{
if (!initialized)
return -1;
int channel;
Mix_Chunk *chunk = GetSoundChunk(sound);
if (chunk)
{
channel = Mix_PlayChannel(-1, chunk, repeats);
if (channel == -1)
tlog1 << "Unable to play sound file " << sound << " , error " << Mix_GetError() << std::endl;
else
callbacks[channel];//insert empty callback
}
else
{
channel = -1;
}
return channel;
}
// Helper. Randomly select a sound from an array and play it
int CSoundHandler::playSoundFromSet(std::vector<soundBase::soundID> &sound_vec)
{

View File

@ -20,30 +20,30 @@ typedef struct _Mix_Music Mix_Music;
struct Mix_Chunk;
// Sound infos for creatures in combat
struct CreaturesBattleSounds {
soundBase::soundID attack;
soundBase::soundID defend;
soundBase::soundID killed; // was killed or died
soundBase::soundID move;
soundBase::soundID shoot; // range attack
soundBase::soundID wince; // attacked but did not die
soundBase::soundID ext1; // creature specific extension
soundBase::soundID ext2; // creature specific extension
soundBase::soundID startMoving; // usually same as ext1
soundBase::soundID endMoving; // usually same as ext2
CreaturesBattleSounds(): attack(soundBase::invalid),
defend(soundBase::invalid),
killed(soundBase::invalid),
move(soundBase::invalid),
shoot(soundBase::invalid),
wince(soundBase::invalid),
ext1(soundBase::invalid),
ext2(soundBase::invalid),
startMoving(soundBase::invalid),
endMoving(soundBase::invalid) {};
};
//// Sound infos for creatures in combat
//struct CreaturesBattleSounds {
// soundBase::soundID attack;
// soundBase::soundID defend;
// soundBase::soundID killed; // was killed or died
// soundBase::soundID move;
// soundBase::soundID shoot; // range attack
// soundBase::soundID wince; // attacked but did not die
// soundBase::soundID ext1; // creature specific extension
// soundBase::soundID ext2; // creature specific extension
// soundBase::soundID startMoving; // usually same as ext1
// soundBase::soundID endMoving; // usually same as ext2
//
// CreaturesBattleSounds(): attack(soundBase::invalid),
// defend(soundBase::invalid),
// killed(soundBase::invalid),
// move(soundBase::invalid),
// shoot(soundBase::invalid),
// wince(soundBase::invalid),
// ext1(soundBase::invalid),
// ext2(soundBase::invalid),
// startMoving(soundBase::invalid),
// endMoving(soundBase::invalid) {};
//};
class CAudioBase {
protected:
@ -70,6 +70,7 @@ private:
std::map<soundBase::soundID, Mix_Chunk *> soundChunks;
Mix_Chunk *GetSoundChunk(soundBase::soundID soundID);
Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound);
//have entry for every currently active channel
//boost::function will be NULL if callback was not set
@ -87,13 +88,13 @@ public:
// Sounds
int playSound(soundBase::soundID soundID, int repeats=0);
int playSound(std::string sound, int repeats=0);
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
void stopSound(int handler);
void setCallback(int channel, boost::function<void()> function);
void soundFinishedCallback(int channel);
std::vector <struct CreaturesBattleSounds> CBattleSounds;
std::map<const CSpell*, soundBase::soundID> spellSounds;
// Sets
@ -102,8 +103,8 @@ public:
std::vector<soundBase::soundID> battleIntroSounds;
};
// Helper
#define battle_sound(creature,what_sound) CCS->soundh->CBattleSounds[(creature)->idNumber].what_sound
// Helper //now it looks somewhat useless
#define battle_sound(creature,what_sound) creature->sounds.what_sound
class CMusicHandler;

View File

@ -466,6 +466,8 @@ void CCreatureHandler::loadCreatures()
buildBonusTreeForTiers();
loadAnimationInfo();
loadSoundsInfo();
//reading creature ability names
const JsonNode config2(ResourceID("config/bonusnames.json"));
@ -691,6 +693,49 @@ void CCreatureHandler::loadUnitAnimInfo(CCreature & unit, std::string & src, int
i+=2;
}
void CCreatureHandler::loadSoundsInfo()
{
tlog5 << "\t\tReading config/cr_sounds.json" << std::endl;
const JsonNode config(ResourceID("config/cr_sounds.json"));
if (!config["creature_sounds"].isNull())
{
BOOST_FOREACH(const JsonNode &node, config["creature_sounds"].Vector())
{
const JsonNode *value;
int id;
value = &node["name"];
bmap<std::string,int>::const_iterator i = nameToID.find(value->String());
if (i != nameToID.end())
id = i->second;
else
{
tlog1 << "Sound info for an unknown creature: " << value->String() << std::endl;
continue;
}
/* This is a bit ugly. Maybe we should use an array for
* sound ids instead of separate variables and define
* attack/defend/killed/... as indexes. */
#define GET_SOUND_VALUE(value_name) do { value = &node[#value_name]; if (!value->isNull()) creatures[id]->sounds.value_name = value->String(); } while(0)
GET_SOUND_VALUE(attack);
GET_SOUND_VALUE(defend);
GET_SOUND_VALUE(killed);
GET_SOUND_VALUE(move);
GET_SOUND_VALUE(shoot);
GET_SOUND_VALUE(wince);
GET_SOUND_VALUE(ext1);
GET_SOUND_VALUE(ext2);
GET_SOUND_VALUE(startMoving);
GET_SOUND_VALUE(endMoving);
#undef GET_SOUND_VALUE
}
}
}
void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser & parser) //help function for parsing CREXPBON.txt
{
bool enable = false; //some bonuses are activated with values 2 or 1

View File

@ -6,6 +6,7 @@
#include "ResourceSet.h"
#include "GameConstants.h"
#include "JsonNode.h"
#include "../client/CMusicHandler.h"
/*
* CCreatureHandler.h, part of VCMI engine
@ -20,6 +21,7 @@
class CLegacyConfigParser;
class CCreatureHandler;
class CCreature;
struct CreaturesBattleSounds;
class DLL_LINKAGE CCreature : public CBonusSystemNode
{
@ -45,6 +47,26 @@ public:
int troopCountLocationOffset, attackClimaxFrame;
///end of anim info
//sound info
struct CreaturesBattleSounds
{
std::string attack;
std::string defend;
std::string killed; // was killed or died
std::string move;
std::string shoot; // range attack
std::string wince; // attacked but did not die
std::string ext1; // creature specific extension
std::string ext2; // creature specific extension
std::string startMoving; // usually same as ext1
std::string endMoving; // usually same as ext2
template <typename Handler> void serialize(Handler &h, const int version)
{
h & attack & defend & killed & move & shoot & wince & ext1 & ext2 & startMoving & endMoving;
}
} sounds;
bool isItNativeTerrain(int terrain) const;
bool isDoubleWide() const; //returns true if unit is double wide on battlefield
bool isFlying() const; //returns true if it is a flying unit
@ -85,6 +107,7 @@ public:
& timeBetweenFidgets & walkAnimationTime & attackAnimationTime & flightAnimationDistance
& upperRightMissleOffsetX & rightMissleOffsetX & lowerRightMissleOffsetX & upperRightMissleOffsetY & rightMissleOffsetY & lowerRightMissleOffsetY
& missleFrameAngles & troopCountLocationOffset & attackClimaxFrame;
h & sounds;
h & doubleWide;
}
@ -126,6 +149,7 @@ public:
void buildBonusTreeForTiers();
void loadAnimationInfo();
void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i);
void loadSoundsInfo();
void loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser &parser);
int stringToNumber(std::string & s);//help function for parsing CREXPBON.txt

View File

@ -165,21 +165,20 @@ CCreature * CModHandler::loadCreature (const JsonNode &node)
//we need to know creature id to add it
VLC->creh->idToProjectile[cre->idNumber] = value->String();
//TODO: sounds
//how to pass info to Client?
auto sounds = node["sound"];
//CreaturesBattleSounds cbs;
//cbs.attack = sounds["attack"].String();
//cbs.defend = sounds["defend"].String();
//cbs.killed = sounds["killed"].String(); // was killed or died
//cbs.move = sounds["move"].String();
//cbs.shoot = sounds["shoot"].String(); // range attack
//cbs.wince = sounds["wince"].String(); // attacked but did not die
//cbs.ext1 = ""; // creature specific extension
//cbs.ext2 = ""; // creature specific extension
//cbs.startMoving = sounds["moveStart"].String(); // usually same as ext1
//cbs.endMoving = sounds["moveEnd"].String(); // usually same as ext2
//CCS->soundh->CBattleSounds.push_back(cbs);
#define GET_SOUND_VALUE(value_name) do { value = &node[#value_name]; if (!value->isNull()) cre->sounds.value_name = sounds[#value_name].String(); } while(0)
GET_SOUND_VALUE(attack);
GET_SOUND_VALUE(defend);
GET_SOUND_VALUE(killed);
GET_SOUND_VALUE(move);
GET_SOUND_VALUE(shoot);
GET_SOUND_VALUE(wince);
GET_SOUND_VALUE(ext1);
GET_SOUND_VALUE(ext2);
GET_SOUND_VALUE(startMoving);
GET_SOUND_VALUE(endMoving);
#undef GET_SOUND_VALUE
creatures.push_back(cre);
return cre;