diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 87cc31954..35fc597fe 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -41,6 +41,14 @@ set(GAMEGUI ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) +set(GAMEDIALOGUE_HEADER + mwdialogue/dialoguemanager.hpp +) +set(GAMEDIALOGUE + mwdialogue/dialoguemanager.cpp +) +source_group(apps\\openmw\\mwdialogue FILES ${GAMEDIALOGUE_HEADER} ${GAMEDIALOGUE}) + set(GAMESCRIPT mwscript/scriptmanager.cpp mwscript/compilercontext.cpp @@ -97,6 +105,7 @@ set(GAMEWORLD_HEADER mwworld/action.hpp mwworld/nullaction.hpp mwworld/actionteleport.hpp + mwworld/containerstore.hpp mwworld/actiontalk.hpp mwworld/actiontake.hpp mwworld/containerstore.hpp @@ -164,11 +173,11 @@ set(GAMEMECHANICS_HEADER source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER}) set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD} - ${GAMECLASS} ${GAMEMECHANICS} + ${GAMECLASS} ${GAMEMECHANICS} ${GAMEDIALOGUE} ) set(OPENMW_HEADER ${GAME_HEADER} ${GAMEREND_HEADER} ${GAMEINPUT_HEADER} ${GAMESCRIPT_HEADER} ${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMECLASS_HEADER} - ${GAMEMECHANICS_HEADER} + ${GAMEMECHANICS_HEADER} ${GAMEDIALOG_HEADERUE} ) # Main executable diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a77ee925e..bcf2de40d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -28,6 +28,8 @@ #include "mwclass/classes.hpp" +#include "mwdialogue/dialoguemanager.hpp" + #include "mwmechanics/mechanicsmanager.hpp" #include @@ -104,6 +106,7 @@ OMW::Engine::Engine() : mDebug (false) , mVerboseScripts (false) , mNewGame (false) + , mUseSound (true) , mScriptManager (0) , mScriptContext (0) { @@ -117,6 +120,7 @@ OMW::Engine::~Engine() delete mEnvironment.mSoundManager; delete mEnvironment.mGlobalScripts; delete mEnvironment.mMechanicsManager; + delete mEnvironment.mDialogueManager; delete mScriptManager; delete mScriptContext; } @@ -236,7 +240,8 @@ void OMW::Engine::go() mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), mOgre.getCamera(), mEnvironment.mWorld->getStore(), - (mDataDir / "Sound").file_string()); + (mDataDir / "Sound").file_string(), + mUseSound); // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, @@ -253,6 +258,9 @@ void OMW::Engine::go() mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager ( mEnvironment.mWorld->getStore(), *mEnvironment.mWindowManager); + // Create dialog system + mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment); + // load cell ESM::Position pos; pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index bc612d13c..d7420889f 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -59,6 +59,7 @@ namespace OMW bool mDebug; bool mVerboseScripts; bool mNewGame; + bool mUseSound; MWWorld::Environment mEnvironment; MWScript::ScriptManager *mScriptManager; @@ -115,6 +116,9 @@ namespace OMW /// Enable verbose script output void enableVerboseScripts(); + /// Disable all sound + void disableSound() { mUseSound = false; } + /// Start as a new game. void setNewGame(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index ff3f32e3d..b622b1f27 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -31,6 +31,7 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) ("master", bpo::value()->default_value ("Morrowind"), "master file") ( "debug", "debug mode" ) + ( "nosound", "disable all sound" ) ( "script-verbose", "verbose script output" ) ( "new-game", "activate char gen/new game mechanics" ) ; @@ -64,6 +65,9 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) if (variables.count ("debug")) engine.enableDebugMode(); + + if (variables.count ("nosound")) + engine.disableSound(); if (variables.count ("script-verbose")) engine.enableVerboseScripts(); diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8757c93fd..fc9515fff 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -15,6 +15,14 @@ namespace MWClass { + std::string Creature::getId (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->mId; + } + void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const { @@ -96,7 +104,7 @@ namespace MWClass } return *ptr.getRefData().getContainerStore(); - } + } std::string Creature::getScript (const MWWorld::Ptr& ptr) const { diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index ec354a015..9f6708f40 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -9,6 +9,9 @@ namespace MWClass { public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 1aae8928d..3bc005b06 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -16,6 +16,14 @@ namespace MWClass { + std::string Npc::getId (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->mId; + } + void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const { diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 1bbf427de..dd54806bd 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -9,6 +9,9 @@ namespace MWClass { public: + virtual std::string getId (const MWWorld::Ptr& ptr) const; + ///< Return ID of \a ptr + virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering @@ -26,14 +29,14 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats - virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; - ///< Generate action for activation - virtual MWWorld::ContainerStore& getContainerStore ( const MWWorld::Ptr& ptr) const; ///< Return container store + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp new file mode 100644 index 000000000..ab369288e --- /dev/null +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -0,0 +1,281 @@ + +#include "dialoguemanager.hpp" + +#include +#include +#include + +#include + +#include + +#include "../mwworld/class.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/refdata.hpp" + +#include "../mwgui/window_manager.hpp" + +#include + +namespace +{ + std::string toLower (const std::string& name) + { + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; + } + + template + bool selectCompare (char comp, T1 value1, T2 value2) + { + switch (comp) + { + case '0': return value1==value2; + case '1': return value1!=value2; + case '2': return value1>value2; + case '3': return value1>=value2; + case '4': return value1 + bool checkLocal (char comp, const std::string& name, T value, const MWWorld::Ptr& actor, + const ESMS::ESMStore& store) + { + std::string scriptName = MWWorld::Class::get (actor).getScript (actor); + + if (scriptName.empty()) + return false; // no script + + const ESM::Script *script = store.scripts.find (scriptName); + + int i = 0; + + for (; i (script->varNames.size()); ++i) + if (script->varNames[i]==name) + break; + + if (i>=static_cast (script->varNames.size())) + return false; // script does not have a variable of this name + + const MWScript::Locals& locals = actor.getRefData().getLocals(); + + if (idata.numShorts) + return selectCompare (comp, locals.mShorts[i], value); + else + i -= script->data.numShorts; + + if (idata.numLongs) + return selectCompare (comp, locals.mLongs[i], value); + else + i -= script->data.numShorts; + + return selectCompare (comp, locals.mFloats.at (i), value); + } + + template + bool checkGlobal (char comp, const std::string& name, T value, MWWorld::World& world) + { + switch (world.getGlobalVariableType (name)) + { + case 's': + + return selectCompare (comp, value, world.getGlobalVariable (name).mShort); + + case 'l': + + return selectCompare (comp, value, world.getGlobalVariable (name).mLong); + + case 'f': + + return selectCompare (comp, value, world.getGlobalVariable (name).mFloat); + + case ' ': + + world.getGlobalVariable (name); // trigger exception + break; + + default: + + throw std::runtime_error ("unsupported gobal variable type"); + } + + return false; + } +} + +namespace MWDialogue +{ + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, + const ESM::DialInfo::SelectStruct& select) const + { + char type = select.selectRule[1]; + + if (type!='0') + { + char comp = select.selectRule[4]; + std::string name = select.selectRule.substr (5); + + // TODO types 4, 5, 6, 7, 8, 9, A, B, C + + switch (type) + { + case '1': // function + + return false; // TODO implement functions + + case '2': // global + + if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || + select.type==ESM::VT_Long) + { + if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld)) + return false; + } + else if (select.type==ESM::VT_Float) + { + if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld)) + return false; + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + + return true; + + case '3': // local + + if (select.type==ESM::VT_Short || select.type==ESM::VT_Int || + select.type==ESM::VT_Long) + { + if (!checkLocal (comp, toLower (name), select.i, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else if (select.type==ESM::VT_Float) + { + if (!checkLocal (comp, toLower (name), select.f, actor, + mEnvironment.mWorld->getStore())) + return false; + } + else + throw std::runtime_error ( + "unsupported variable type in dialogue info select"); + + return true; + + default: + + std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; + } + } + + return true; + } + + bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const + { + // actor id + if (!info.actor.empty()) + if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor)) + return false; + + if (!info.race.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (toLower (info.race)!=toLower (cellRef->base->race)) + return false; + } + + if (!info.clas.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (toLower (info.clas)!=toLower (cellRef->base->cls)) + return false; + } + + if (!info.npcFaction.empty()) + { + ESMS::LiveCellRef *cellRef = actor.get(); + + if (!cellRef) + return false; + + if (toLower (info.npcFaction)!=toLower (cellRef->base->faction)) + return false; + } + + // TODO check player faction + + // check cell + if (!info.cell.empty()) + if (mEnvironment.mWorld->getPlayerPos().getPlayer().getCell()->cell->name != info.cell) + return false; + + // TODO check DATAstruct + + for (std::vector::const_iterator iter (info.selects.begin()); + iter != info.selects.end(); ++iter) + if (!isMatching (actor, *iter)) + return false; + + std::cout + << "unchecked entries:" << std::endl + << " player faction: " << info.pcFaction << std::endl + << " DATAstruct" << std::endl; + + return true; + } + + DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {} + + void DialogueManager::startDialogue (const MWWorld::Ptr& actor) + { + std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl; + + const ESM::Dialogue *dialogue = mEnvironment.mWorld->getStore().dialogs.find ("hello"); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + { + if (isMatching (actor, *iter)) + { + // start dialogue + std::cout << "found matching info record" << std::endl; + + std::cout << "response: " << iter->response << std::endl; + + if (!iter->sound.empty()) + { + // TODO play sound + } + + if (!iter->resultScript.empty()) + { + std::cout << "script: " << iter->resultScript << std::endl; + // TODO execute script + } + + mEnvironment.mWindowManager->setMode (MWGui::GM_Dialogue); + break; + } + } + } + +} diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp new file mode 100644 index 000000000..5b6b26240 --- /dev/null +++ b/apps/openmw/mwdialogue/dialoguemanager.hpp @@ -0,0 +1,32 @@ +#ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H +#define GAME_MWDIALOG_DIALOGUEMANAGER_H + +#include + +#include "../mwworld/ptr.hpp" + +namespace MWWorld +{ + class Environment; +} + +namespace MWDialogue +{ + class DialogueManager + { + MWWorld::Environment& mEnvironment; + + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo::SelectStruct& select) const; + + bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const; + + public: + + DialogueManager (MWWorld::Environment& environment); + + void startDialogue (const MWWorld::Ptr& actor); + + }; +} + +#endif diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index f8f5eeb00..f800a39e3 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -20,16 +20,22 @@ using namespace std; #ifdef OPENMW_USE_AUDIERE #include #define SOUND_FACTORY OpenAL_Audiere_Factory +#define SOUND_OUT "OpenAL" +#define SOUND_IN "Audiere" #endif #ifdef OPENMW_USE_FFMPEG #include #define SOUND_FACTORY OpenAL_FFMpeg_Factory +#define SOUND_OUT "OpenAL" +#define SOUND_IN "FFmpeg" #endif #ifdef OPENMW_USE_MPG123 #include #define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory +#define SOUND_OUT "OpenAL" +#define SOUND_IN "mpg123,sndfile" #endif using namespace Mangle::Sound; @@ -77,6 +83,9 @@ namespace MWSound , cameraTracker(mgr) , store(str) { + cout << "Sound output: " << SOUND_OUT << endl; + cout << "Sound decoder: " << SOUND_IN << endl; + // Attach the camera to the camera tracker cameraTracker.followCamera(camera); @@ -150,29 +159,37 @@ namespace MWSound SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, const ESMS::ESMStore &store, - const std::string &soundDir) + const std::string &soundDir, + bool useSound) + : mData(NULL) { - mData = new SoundImpl(root, camera, store, soundDir); + if(useSound) + mData = new SoundImpl(root, camera, store, soundDir); } SoundManager::~SoundManager() { - delete mData; + if(mData) + delete mData; } void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) { // The range values are not tested + if(!mData) return; mData->add(filename, ptr, "_say_sound", 1, 1, 100, 10000, false); } bool SoundManager::sayDone (MWWorld::Ptr ptr) const { + if(!mData) return false; return !mData->isPlaying(ptr, "_say_sound"); } void SoundManager::streamMusic (const std::string& filename) { + if(!mData) return; + // Play the sound and tell it to stream, if possible. TODO: // Store the reference, the jukebox will need to check status, // control volume etc. @@ -184,6 +201,8 @@ namespace MWSound void SoundManager::playSound (const std::string& soundId, float volume, float pitch) { + if(!mData) return; + // Play and forget float min, max; const std::string &file = mData->lookup(soundId, volume, min, max); @@ -199,6 +218,8 @@ namespace MWSound void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, float volume, float pitch, bool loop) { + if(!mData) return; + // Look up the sound in the ESM data float min, max; const std::string &file = mData->lookup(soundId, volume, min, max); @@ -208,21 +229,28 @@ namespace MWSound void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId) { + if(!mData) return; mData->remove(ptr, soundId); } void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) { + if(!mData) return; mData->removeCell(cell); } bool SoundManager::getSoundPlaying (MWWorld::Ptr ptr, const std::string& soundId) const { + // Mark all sounds as playing, otherwise the scripts will just + // keep trying to play them every frame. + if(!mData) return true; + return mData->isPlaying(ptr, soundId); } void SoundManager::updateObject(MWWorld::Ptr ptr) { + if(!mData) return; mData->updatePositions(ptr); } } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index 9b4745203..9f99b34b2 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -28,7 +28,7 @@ namespace MWSound public: SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, - const std::string &soundDir); + const std::string &soundDir, bool useSound); ~SoundManager(); void say (MWWorld::Ptr reference, const std::string& filename); diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 2b4aba735..7d38c22fd 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -3,7 +3,7 @@ #include "environment.hpp" -#include "../mwgui/window_manager.hpp" +#include "../mwdialogue/dialoguemanager.hpp" namespace MWWorld { @@ -11,6 +11,6 @@ namespace MWWorld void ActionTalk::execute (Environment& environment) { - environment.mWindowManager->setMode (MWGui::GM_Dialogue); + environment.mDialogueManager->startDialogue (mActor); } } diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index 034d6131c..a60a61660 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -13,6 +13,7 @@ namespace MWWorld public: ActionTalk (const Ptr& actor); + ///< \param actor The actor the player is talking to virtual void execute (Environment& environment); }; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 386ba650e..bc36944e6 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -14,6 +14,11 @@ namespace MWWorld Class::~Class() {} + std::string Class::getId (const Ptr& ptr) const + { + throw std::runtime_error ("class does not support ID retrieval"); + } + void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index d230605da..4b6644e96 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -42,6 +42,10 @@ namespace MWWorld virtual ~Class(); + virtual std::string getId (const Ptr& ptr) const; + ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval + /// (default implementation: throw an exception) + virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp index 0c6476d52..f9e2e8a42 100644 --- a/apps/openmw/mwworld/environment.hpp +++ b/apps/openmw/mwworld/environment.hpp @@ -21,17 +21,22 @@ namespace MWMechanics class MechanicsManager; } +namespace MWDialogue +{ + class DialogueManager; +} + namespace MWWorld { class World; ///< Collection of script-accessable sub-systems class Environment - { + { public: Environment() : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), - mMechanicsManager (0), mFrameDuration (0) + mMechanicsManager (0), mDialogueManager (0), mFrameDuration (0) {} World *mWorld; @@ -39,9 +44,9 @@ namespace MWWorld MWScript::GlobalScripts *mGlobalScripts; MWGui::WindowManager *mWindowManager; MWMechanics::MechanicsManager *mMechanicsManager; + MWDialogue::DialogueManager *mDialogueManager; float mFrameDuration; }; } #endif - diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 4c80fc783..c435eb276 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -1,7 +1,10 @@ #ifndef _ESM_DIAL_H #define _ESM_DIAL_H +#include + #include "esm_reader.hpp" +#include "loadinfo.hpp" namespace ESM { @@ -23,6 +26,7 @@ struct Dialogue }; char type; + std::vector mInfo; void load(ESMReader &esm) { diff --git a/components/esm/records.hpp b/components/esm/records.hpp index 4ef8ce564..fb5733c63 100644 --- a/components/esm/records.hpp +++ b/components/esm/records.hpp @@ -14,13 +14,13 @@ #include "loadcont.hpp" #include "loadcrea.hpp" #include "loadcrec.hpp" +#include "loadinfo.hpp" #include "loaddial.hpp" #include "loaddoor.hpp" #include "loadench.hpp" #include "loadfact.hpp" #include "loadglob.hpp" #include "loadgmst.hpp" -#include "loadinfo.hpp" #include "loadingr.hpp" #include "loadland.hpp" #include "loadlevlist.hpp" diff --git a/components/esm_store/store.cpp b/components/esm_store/store.cpp index 2016272e0..c43855873 100644 --- a/components/esm_store/store.cpp +++ b/components/esm_store/store.cpp @@ -18,32 +18,70 @@ static string toStr(int i) void ESMStore::load(ESMReader &esm) { - set missing; + set missing; - // Loop through all records - while(esm.hasMoreRecs()) + ESM::Dialogue *dialogue = 0; + + // Loop through all records + while(esm.hasMoreRecs()) { - NAME n = esm.getRecName(); - esm.getRecHeader(); + NAME n = esm.getRecName(); + esm.getRecHeader(); - // Look up the record type. - RecListList::iterator it = recLists.find(n.val); + // Look up the record type. + RecListList::iterator it = recLists.find(n.val); - if(it == recLists.end()) + if(it == recLists.end()) { - // Not found (this would be an error later) - esm.skipRecord(); - missing.insert(n.toString()); - continue; + if (n.val==ESM::REC_INFO) + { + if (dialogue) + { + ESM::DialInfo info; + info.load (esm); + + dialogue->mInfo.push_back (info); + } + else + { + std::cerr << "error: info record without dialog" << std::endl; + esm.skipRecord(); + continue; + } + } + else + { + // Not found (this would be an error later) + esm.skipRecord(); + missing.insert(n.toString()); + continue; + } } + else + { + // Load it + std::string id = esm.getHNOString("NAME"); + it->second->load(esm, id); + + if (n.val==ESM::REC_DIAL) + { + RecListT& recList = static_cast& > (*it->second); - // Load it - std::string id = esm.getHNOString("NAME"); - it->second->load(esm, id); + id = recList.toLower (id); - // Insert the reference into the global lookup - if(!id.empty()) - all[id] = n.val; + RecListT::MapType::iterator iter = recList.list.find (id); + + assert (iter!=recList.list.end()); + + dialogue = &iter->second; + } + else + dialogue = 0; + + // Insert the reference into the global lookup + if(!id.empty()) + all[id] = n.val; + } } /* This information isn't needed on screen. But keep the code around diff --git a/components/esm_store/store.hpp b/components/esm_store/store.hpp index 6138014ef..1b9184aa6 100644 --- a/components/esm_store/store.hpp +++ b/components/esm_store/store.hpp @@ -69,7 +69,6 @@ namespace ESMS // Lists that need special rules CellList cells; RecIDListT gameSettings; - //RecListT dialInfos; //RecListT lands; //RecListT landTexts; //RecListT magicEffects; @@ -92,7 +91,6 @@ namespace ESMS ESMStore() { - recLists[REC_ACTI] = &activators; recLists[REC_ACTI] = &activators; recLists[REC_ALCH] = &potions; recLists[REC_APPA] = &appas; @@ -113,7 +111,6 @@ namespace ESMS recLists[REC_FACT] = &factions; recLists[REC_GLOB] = &globals; recLists[REC_GMST] = &gameSettings; - //recLists[REC_INFO] = &dialInfos; recLists[REC_INGR] = &ingreds; //recLists[REC_LAND] = &lands; recLists[REC_LEVC] = &creatureLists; diff --git a/libs/mangle b/libs/mangle index cd4ed4e6b..200fab03e 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit cd4ed4e6bfb23d736c4b1f30d6096ec164ba937b +Subproject commit 200fab03efaa2cbe1b8fce4a742b0195f8912295