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:
parent
061ed69c63
commit
9438cfc7e2
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user