mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Moved creature sounds to CCreature. Sound IDs are now stored as strings.
Creature parser is complete (untested).
This commit is contained in:
@@ -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
|
// Get a soundID given a filename
|
||||||
soundBase::soundID CSoundHandler::getSoundID(const std::string &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)
|
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
|
//commented to avoid spurious warnings
|
||||||
/*
|
/*
|
||||||
@@ -269,6 +248,30 @@ int CSoundHandler::playSound(soundBase::soundID soundID, int repeats)
|
|||||||
return channel;
|
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
|
// Helper. Randomly select a sound from an array and play it
|
||||||
int CSoundHandler::playSoundFromSet(std::vector<soundBase::soundID> &sound_vec)
|
int CSoundHandler::playSoundFromSet(std::vector<soundBase::soundID> &sound_vec)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,30 +20,30 @@ typedef struct _Mix_Music Mix_Music;
|
|||||||
struct Mix_Chunk;
|
struct Mix_Chunk;
|
||||||
|
|
||||||
|
|
||||||
// Sound infos for creatures in combat
|
//// Sound infos for creatures in combat
|
||||||
struct CreaturesBattleSounds {
|
//struct CreaturesBattleSounds {
|
||||||
soundBase::soundID attack;
|
// soundBase::soundID attack;
|
||||||
soundBase::soundID defend;
|
// soundBase::soundID defend;
|
||||||
soundBase::soundID killed; // was killed or died
|
// soundBase::soundID killed; // was killed or died
|
||||||
soundBase::soundID move;
|
// soundBase::soundID move;
|
||||||
soundBase::soundID shoot; // range attack
|
// soundBase::soundID shoot; // range attack
|
||||||
soundBase::soundID wince; // attacked but did not die
|
// soundBase::soundID wince; // attacked but did not die
|
||||||
soundBase::soundID ext1; // creature specific extension
|
// soundBase::soundID ext1; // creature specific extension
|
||||||
soundBase::soundID ext2; // creature specific extension
|
// soundBase::soundID ext2; // creature specific extension
|
||||||
soundBase::soundID startMoving; // usually same as ext1
|
// soundBase::soundID startMoving; // usually same as ext1
|
||||||
soundBase::soundID endMoving; // usually same as ext2
|
// soundBase::soundID endMoving; // usually same as ext2
|
||||||
|
//
|
||||||
CreaturesBattleSounds(): attack(soundBase::invalid),
|
// CreaturesBattleSounds(): attack(soundBase::invalid),
|
||||||
defend(soundBase::invalid),
|
// defend(soundBase::invalid),
|
||||||
killed(soundBase::invalid),
|
// killed(soundBase::invalid),
|
||||||
move(soundBase::invalid),
|
// move(soundBase::invalid),
|
||||||
shoot(soundBase::invalid),
|
// shoot(soundBase::invalid),
|
||||||
wince(soundBase::invalid),
|
// wince(soundBase::invalid),
|
||||||
ext1(soundBase::invalid),
|
// ext1(soundBase::invalid),
|
||||||
ext2(soundBase::invalid),
|
// ext2(soundBase::invalid),
|
||||||
startMoving(soundBase::invalid),
|
// startMoving(soundBase::invalid),
|
||||||
endMoving(soundBase::invalid) {};
|
// endMoving(soundBase::invalid) {};
|
||||||
};
|
//};
|
||||||
|
|
||||||
class CAudioBase {
|
class CAudioBase {
|
||||||
protected:
|
protected:
|
||||||
@@ -70,6 +70,7 @@ private:
|
|||||||
std::map<soundBase::soundID, Mix_Chunk *> soundChunks;
|
std::map<soundBase::soundID, Mix_Chunk *> soundChunks;
|
||||||
|
|
||||||
Mix_Chunk *GetSoundChunk(soundBase::soundID soundID);
|
Mix_Chunk *GetSoundChunk(soundBase::soundID soundID);
|
||||||
|
Mix_Chunk *CSoundHandler::GetSoundChunk(std::string &sound);
|
||||||
|
|
||||||
//have entry for every currently active channel
|
//have entry for every currently active channel
|
||||||
//boost::function will be NULL if callback was not set
|
//boost::function will be NULL if callback was not set
|
||||||
@@ -87,13 +88,13 @@ 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);
|
||||||
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
|
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
|
||||||
void stopSound(int handler);
|
void stopSound(int handler);
|
||||||
|
|
||||||
void setCallback(int channel, boost::function<void()> function);
|
void setCallback(int channel, boost::function<void()> function);
|
||||||
void soundFinishedCallback(int channel);
|
void soundFinishedCallback(int channel);
|
||||||
|
|
||||||
std::vector <struct CreaturesBattleSounds> CBattleSounds;
|
|
||||||
std::map<const CSpell*, soundBase::soundID> spellSounds;
|
std::map<const CSpell*, soundBase::soundID> spellSounds;
|
||||||
|
|
||||||
// Sets
|
// Sets
|
||||||
@@ -102,8 +103,8 @@ public:
|
|||||||
std::vector<soundBase::soundID> battleIntroSounds;
|
std::vector<soundBase::soundID> battleIntroSounds;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper
|
// Helper //now it looks somewhat useless
|
||||||
#define battle_sound(creature,what_sound) CCS->soundh->CBattleSounds[(creature)->idNumber].what_sound
|
#define battle_sound(creature,what_sound) creature->sounds.what_sound
|
||||||
|
|
||||||
class CMusicHandler;
|
class CMusicHandler;
|
||||||
|
|
||||||
|
|||||||
@@ -466,6 +466,8 @@ void CCreatureHandler::loadCreatures()
|
|||||||
|
|
||||||
buildBonusTreeForTiers();
|
buildBonusTreeForTiers();
|
||||||
loadAnimationInfo();
|
loadAnimationInfo();
|
||||||
|
loadSoundsInfo();
|
||||||
|
|
||||||
|
|
||||||
//reading creature ability names
|
//reading creature ability names
|
||||||
const JsonNode config2(ResourceID("config/bonusnames.json"));
|
const JsonNode config2(ResourceID("config/bonusnames.json"));
|
||||||
@@ -691,6 +693,49 @@ void CCreatureHandler::loadUnitAnimInfo(CCreature & unit, std::string & src, int
|
|||||||
i+=2;
|
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
|
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
|
bool enable = false; //some bonuses are activated with values 2 or 1
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "ResourceSet.h"
|
#include "ResourceSet.h"
|
||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
|
#include "../client/CMusicHandler.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CCreatureHandler.h, part of VCMI engine
|
* CCreatureHandler.h, part of VCMI engine
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
class CLegacyConfigParser;
|
class CLegacyConfigParser;
|
||||||
class CCreatureHandler;
|
class CCreatureHandler;
|
||||||
class CCreature;
|
class CCreature;
|
||||||
|
struct CreaturesBattleSounds;
|
||||||
|
|
||||||
class DLL_LINKAGE CCreature : public CBonusSystemNode
|
class DLL_LINKAGE CCreature : public CBonusSystemNode
|
||||||
{
|
{
|
||||||
@@ -45,6 +47,26 @@ public:
|
|||||||
int troopCountLocationOffset, attackClimaxFrame;
|
int troopCountLocationOffset, attackClimaxFrame;
|
||||||
///end of anim info
|
///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 isItNativeTerrain(int terrain) const;
|
||||||
bool isDoubleWide() const; //returns true if unit is double wide on battlefield
|
bool isDoubleWide() const; //returns true if unit is double wide on battlefield
|
||||||
bool isFlying() const; //returns true if it is a flying unit
|
bool isFlying() const; //returns true if it is a flying unit
|
||||||
@@ -85,6 +107,7 @@ public:
|
|||||||
& timeBetweenFidgets & walkAnimationTime & attackAnimationTime & flightAnimationDistance
|
& timeBetweenFidgets & walkAnimationTime & attackAnimationTime & flightAnimationDistance
|
||||||
& upperRightMissleOffsetX & rightMissleOffsetX & lowerRightMissleOffsetX & upperRightMissleOffsetY & rightMissleOffsetY & lowerRightMissleOffsetY
|
& upperRightMissleOffsetX & rightMissleOffsetX & lowerRightMissleOffsetX & upperRightMissleOffsetY & rightMissleOffsetY & lowerRightMissleOffsetY
|
||||||
& missleFrameAngles & troopCountLocationOffset & attackClimaxFrame;
|
& missleFrameAngles & troopCountLocationOffset & attackClimaxFrame;
|
||||||
|
h & sounds;
|
||||||
|
|
||||||
h & doubleWide;
|
h & doubleWide;
|
||||||
}
|
}
|
||||||
@@ -126,6 +149,7 @@ public:
|
|||||||
void buildBonusTreeForTiers();
|
void buildBonusTreeForTiers();
|
||||||
void loadAnimationInfo();
|
void loadAnimationInfo();
|
||||||
void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i);
|
void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i);
|
||||||
|
void loadSoundsInfo();
|
||||||
void loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser &parser);
|
void loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser &parser);
|
||||||
int stringToNumber(std::string & s);//help function for parsing CREXPBON.txt
|
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
|
//we need to know creature id to add it
|
||||||
VLC->creh->idToProjectile[cre->idNumber] = value->String();
|
VLC->creh->idToProjectile[cre->idNumber] = value->String();
|
||||||
|
|
||||||
//TODO: sounds
|
|
||||||
//how to pass info to Client?
|
|
||||||
auto sounds = node["sound"];
|
auto sounds = node["sound"];
|
||||||
//CreaturesBattleSounds cbs;
|
|
||||||
//cbs.attack = sounds["attack"].String();
|
#define GET_SOUND_VALUE(value_name) do { value = &node[#value_name]; if (!value->isNull()) cre->sounds.value_name = sounds[#value_name].String(); } while(0)
|
||||||
//cbs.defend = sounds["defend"].String();
|
GET_SOUND_VALUE(attack);
|
||||||
//cbs.killed = sounds["killed"].String(); // was killed or died
|
GET_SOUND_VALUE(defend);
|
||||||
//cbs.move = sounds["move"].String();
|
GET_SOUND_VALUE(killed);
|
||||||
//cbs.shoot = sounds["shoot"].String(); // range attack
|
GET_SOUND_VALUE(move);
|
||||||
//cbs.wince = sounds["wince"].String(); // attacked but did not die
|
GET_SOUND_VALUE(shoot);
|
||||||
//cbs.ext1 = ""; // creature specific extension
|
GET_SOUND_VALUE(wince);
|
||||||
//cbs.ext2 = ""; // creature specific extension
|
GET_SOUND_VALUE(ext1);
|
||||||
//cbs.startMoving = sounds["moveStart"].String(); // usually same as ext1
|
GET_SOUND_VALUE(ext2);
|
||||||
//cbs.endMoving = sounds["moveEnd"].String(); // usually same as ext2
|
GET_SOUND_VALUE(startMoving);
|
||||||
//CCS->soundh->CBattleSounds.push_back(cbs);
|
GET_SOUND_VALUE(endMoving);
|
||||||
|
#undef GET_SOUND_VALUE
|
||||||
|
|
||||||
creatures.push_back(cre);
|
creatures.push_back(cre);
|
||||||
return cre;
|
return cre;
|
||||||
|
|||||||
Reference in New Issue
Block a user