Merge remote branch 'upstream/master'

actorid
Armin Preiml 15 years ago
commit 927879d23e

@ -41,6 +41,14 @@ set(GAMEGUI
) )
source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${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 set(GAMESCRIPT
mwscript/scriptmanager.cpp mwscript/scriptmanager.cpp
mwscript/compilercontext.cpp mwscript/compilercontext.cpp
@ -97,6 +105,7 @@ set(GAMEWORLD_HEADER
mwworld/action.hpp mwworld/action.hpp
mwworld/nullaction.hpp mwworld/nullaction.hpp
mwworld/actionteleport.hpp mwworld/actionteleport.hpp
mwworld/containerstore.hpp
mwworld/actiontalk.hpp mwworld/actiontalk.hpp
mwworld/actiontake.hpp mwworld/actiontake.hpp
mwworld/containerstore.hpp mwworld/containerstore.hpp
@ -164,11 +173,11 @@ set(GAMEMECHANICS_HEADER
source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER}) source_group(apps\\openmw\\mwmechanics FILES ${GAMEMECHANICS} ${GAMEMECHANICS_HEADER})
set(OPENMW_CPP ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT} ${GAMESOUND} ${GAMEGUI} ${GAMEWORLD} 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} set(OPENMW_HEADER ${GAME_HEADER} ${GAMEREND_HEADER} ${GAMEINPUT_HEADER} ${GAMESCRIPT_HEADER}
${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMECLASS_HEADER} ${GAMESOUND_HEADER} ${GAMEGUI_HEADER} ${GAMEWORLD_HEADER} ${GAMECLASS_HEADER}
${GAMEMECHANICS_HEADER} ${GAMEMECHANICS_HEADER} ${GAMEDIALOG_HEADERUE}
) )
# Main executable # Main executable

@ -28,6 +28,8 @@
#include "mwclass/classes.hpp" #include "mwclass/classes.hpp"
#include "mwdialogue/dialoguemanager.hpp"
#include "mwmechanics/mechanicsmanager.hpp" #include "mwmechanics/mechanicsmanager.hpp"
#include <OgreRoot.h> #include <OgreRoot.h>
@ -104,6 +106,7 @@ OMW::Engine::Engine()
: mDebug (false) : mDebug (false)
, mVerboseScripts (false) , mVerboseScripts (false)
, mNewGame (false) , mNewGame (false)
, mUseSound (true)
, mScriptManager (0) , mScriptManager (0)
, mScriptContext (0) , mScriptContext (0)
{ {
@ -117,6 +120,7 @@ OMW::Engine::~Engine()
delete mEnvironment.mSoundManager; delete mEnvironment.mSoundManager;
delete mEnvironment.mGlobalScripts; delete mEnvironment.mGlobalScripts;
delete mEnvironment.mMechanicsManager; delete mEnvironment.mMechanicsManager;
delete mEnvironment.mDialogueManager;
delete mScriptManager; delete mScriptManager;
delete mScriptContext; delete mScriptContext;
} }
@ -236,7 +240,8 @@ void OMW::Engine::go()
mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(), mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre.getRoot(),
mOgre.getCamera(), mOgre.getCamera(),
mEnvironment.mWorld->getStore(), mEnvironment.mWorld->getStore(),
(mDataDir / "Sound").file_string()); (mDataDir / "Sound").file_string(),
mUseSound);
// Create script system // Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full, mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
@ -253,6 +258,9 @@ void OMW::Engine::go()
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager ( mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (
mEnvironment.mWorld->getStore(), *mEnvironment.mWindowManager); mEnvironment.mWorld->getStore(), *mEnvironment.mWindowManager);
// Create dialog system
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment);
// load cell // load cell
ESM::Position pos; ESM::Position pos;
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;

@ -59,6 +59,7 @@ namespace OMW
bool mDebug; bool mDebug;
bool mVerboseScripts; bool mVerboseScripts;
bool mNewGame; bool mNewGame;
bool mUseSound;
MWWorld::Environment mEnvironment; MWWorld::Environment mEnvironment;
MWScript::ScriptManager *mScriptManager; MWScript::ScriptManager *mScriptManager;
@ -115,6 +116,9 @@ namespace OMW
/// Enable verbose script output /// Enable verbose script output
void enableVerboseScripts(); void enableVerboseScripts();
/// Disable all sound
void disableSound() { mUseSound = false; }
/// Start as a new game. /// Start as a new game.
void setNewGame(); void setNewGame();

@ -31,6 +31,7 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
("master", bpo::value<std::string>()->default_value ("Morrowind"), ("master", bpo::value<std::string>()->default_value ("Morrowind"),
"master file") "master file")
( "debug", "debug mode" ) ( "debug", "debug mode" )
( "nosound", "disable all sound" )
( "script-verbose", "verbose script output" ) ( "script-verbose", "verbose script output" )
( "new-game", "activate char gen/new game mechanics" ) ( "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")) if (variables.count ("debug"))
engine.enableDebugMode(); engine.enableDebugMode();
if (variables.count ("nosound"))
engine.disableSound();
if (variables.count ("script-verbose")) if (variables.count ("script-verbose"))
engine.enableVerboseScripts(); engine.enableVerboseScripts();

@ -15,6 +15,14 @@
namespace MWClass namespace MWClass
{ {
std::string Creature::getId (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
ptr.get<ESM::Creature>();
return ref->base->mId;
}
void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const MWWorld::Environment& environment) const
{ {
@ -96,7 +104,7 @@ namespace MWClass
} }
return *ptr.getRefData().getContainerStore(); return *ptr.getRefData().getContainerStore();
} }
std::string Creature::getScript (const MWWorld::Ptr& ptr) const std::string Creature::getScript (const MWWorld::Ptr& ptr) const
{ {

@ -9,6 +9,9 @@ namespace MWClass
{ {
public: 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, virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const; MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering ///< Add reference into a cell for rendering

@ -16,6 +16,14 @@
namespace MWClass namespace MWClass
{ {
std::string Npc::getId (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>();
return ref->base->mId;
}
void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const MWWorld::Environment& environment) const
{ {

@ -9,6 +9,9 @@ namespace MWClass
{ {
public: 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, virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const; MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering ///< Add reference into a cell for rendering
@ -26,14 +29,14 @@ namespace MWClass
virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const;
///< Return creature stats ///< Return creature stats
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
///< Generate action for activation
virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore ( virtual MWWorld::ContainerStore<MWWorld::RefData>& getContainerStore (
const MWWorld::Ptr& ptr) const; const MWWorld::Ptr& ptr) const;
///< Return container store ///< Return container store
virtual boost::shared_ptr<MWWorld::Action> 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; virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr ///< Return name of the script attached to ptr

@ -0,0 +1,281 @@
#include "dialoguemanager.hpp"
#include <cctype>
#include <algorithm>
#include <iterator>
#include <components/esm/loaddial.hpp>
#include <components/esm_store/store.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/refdata.hpp"
#include "../mwgui/window_manager.hpp"
#include <iostream>
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<typename T1, typename T2>
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<value2;
case '5': return value1<=value2;
}
throw std::runtime_error ("unknown compare type in dialogue info select");
}
template<typename T>
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<static_cast<int> (script->varNames.size()); ++i)
if (script->varNames[i]==name)
break;
if (i>=static_cast<int> (script->varNames.size()))
return false; // script does not have a variable of this name
const MWScript::Locals& locals = actor.getRefData().getLocals();
if (i<script->data.numShorts)
return selectCompare (comp, locals.mShorts[i], value);
else
i -= script->data.numShorts;
if (i<script->data.numLongs)
return selectCompare (comp, locals.mLongs[i], value);
else
i -= script->data.numShorts;
return selectCompare (comp, locals.mFloats.at (i), value);
}
template<typename T>
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<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
if (!cellRef)
return false;
if (toLower (info.race)!=toLower (cellRef->base->race))
return false;
}
if (!info.clas.empty())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
if (!cellRef)
return false;
if (toLower (info.clas)!=toLower (cellRef->base->cls))
return false;
}
if (!info.npcFaction.empty())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
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<ESM::DialInfo::SelectStruct>::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<ESM::DialInfo>::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;
}
}
}
}

@ -0,0 +1,32 @@
#ifndef GAME_MMDIALOG_DIALOGUEMANAGER_H
#define GAME_MWDIALOG_DIALOGUEMANAGER_H
#include <components/esm/loadinfo.hpp>
#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

@ -20,16 +20,22 @@ using namespace std;
#ifdef OPENMW_USE_AUDIERE #ifdef OPENMW_USE_AUDIERE
#include <mangle/sound/filters/openal_audiere.hpp> #include <mangle/sound/filters/openal_audiere.hpp>
#define SOUND_FACTORY OpenAL_Audiere_Factory #define SOUND_FACTORY OpenAL_Audiere_Factory
#define SOUND_OUT "OpenAL"
#define SOUND_IN "Audiere"
#endif #endif
#ifdef OPENMW_USE_FFMPEG #ifdef OPENMW_USE_FFMPEG
#include <mangle/sound/filters/openal_ffmpeg.hpp> #include <mangle/sound/filters/openal_ffmpeg.hpp>
#define SOUND_FACTORY OpenAL_FFMpeg_Factory #define SOUND_FACTORY OpenAL_FFMpeg_Factory
#define SOUND_OUT "OpenAL"
#define SOUND_IN "FFmpeg"
#endif #endif
#ifdef OPENMW_USE_MPG123 #ifdef OPENMW_USE_MPG123
#include <mangle/sound/filters/openal_sndfile_mpg123.hpp> #include <mangle/sound/filters/openal_sndfile_mpg123.hpp>
#define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory #define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory
#define SOUND_OUT "OpenAL"
#define SOUND_IN "mpg123,sndfile"
#endif #endif
using namespace Mangle::Sound; using namespace Mangle::Sound;
@ -77,6 +83,9 @@ namespace MWSound
, cameraTracker(mgr) , cameraTracker(mgr)
, store(str) , store(str)
{ {
cout << "Sound output: " << SOUND_OUT << endl;
cout << "Sound decoder: " << SOUND_IN << endl;
// Attach the camera to the camera tracker // Attach the camera to the camera tracker
cameraTracker.followCamera(camera); cameraTracker.followCamera(camera);
@ -150,29 +159,37 @@ namespace MWSound
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
const ESMS::ESMStore &store, 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() SoundManager::~SoundManager()
{ {
delete mData; if(mData)
delete mData;
} }
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
{ {
// The range values are not tested // The range values are not tested
if(!mData) return;
mData->add(filename, ptr, "_say_sound", 1, 1, 100, 10000, false); mData->add(filename, ptr, "_say_sound", 1, 1, 100, 10000, false);
} }
bool SoundManager::sayDone (MWWorld::Ptr ptr) const bool SoundManager::sayDone (MWWorld::Ptr ptr) const
{ {
if(!mData) return false;
return !mData->isPlaying(ptr, "_say_sound"); return !mData->isPlaying(ptr, "_say_sound");
} }
void SoundManager::streamMusic (const std::string& filename) void SoundManager::streamMusic (const std::string& filename)
{ {
if(!mData) return;
// Play the sound and tell it to stream, if possible. TODO: // Play the sound and tell it to stream, if possible. TODO:
// Store the reference, the jukebox will need to check status, // Store the reference, the jukebox will need to check status,
// control volume etc. // control volume etc.
@ -184,6 +201,8 @@ namespace MWSound
void SoundManager::playSound (const std::string& soundId, float volume, float pitch) void SoundManager::playSound (const std::string& soundId, float volume, float pitch)
{ {
if(!mData) return;
// Play and forget // Play and forget
float min, max; float min, max;
const std::string &file = mData->lookup(soundId, volume, 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, void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId,
float volume, float pitch, bool loop) float volume, float pitch, bool loop)
{ {
if(!mData) return;
// Look up the sound in the ESM data // Look up the sound in the ESM data
float min, max; float min, max;
const std::string &file = mData->lookup(soundId, volume, 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) void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId)
{ {
if(!mData) return;
mData->remove(ptr, soundId); mData->remove(ptr, soundId);
} }
void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell)
{ {
if(!mData) return;
mData->removeCell(cell); mData->removeCell(cell);
} }
bool SoundManager::getSoundPlaying (MWWorld::Ptr ptr, const std::string& soundId) const 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); return mData->isPlaying(ptr, soundId);
} }
void SoundManager::updateObject(MWWorld::Ptr ptr) void SoundManager::updateObject(MWWorld::Ptr ptr)
{ {
if(!mData) return;
mData->updatePositions(ptr); mData->updatePositions(ptr);
} }
} }

@ -28,7 +28,7 @@ namespace MWSound
public: public:
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store, SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
const std::string &soundDir); const std::string &soundDir, bool useSound);
~SoundManager(); ~SoundManager();
void say (MWWorld::Ptr reference, const std::string& filename); void say (MWWorld::Ptr reference, const std::string& filename);

@ -3,7 +3,7 @@
#include "environment.hpp" #include "environment.hpp"
#include "../mwgui/window_manager.hpp" #include "../mwdialogue/dialoguemanager.hpp"
namespace MWWorld namespace MWWorld
{ {
@ -11,6 +11,6 @@ namespace MWWorld
void ActionTalk::execute (Environment& environment) void ActionTalk::execute (Environment& environment)
{ {
environment.mWindowManager->setMode (MWGui::GM_Dialogue); environment.mDialogueManager->startDialogue (mActor);
} }
} }

@ -13,6 +13,7 @@ namespace MWWorld
public: public:
ActionTalk (const Ptr& actor); ActionTalk (const Ptr& actor);
///< \param actor The actor the player is talking to
virtual void execute (Environment& environment); virtual void execute (Environment& environment);
}; };

@ -14,6 +14,11 @@ namespace MWWorld
Class::~Class() {} 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, void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const MWWorld::Environment& environment) const
{ {

@ -42,6 +42,10 @@ namespace MWWorld
virtual ~Class(); 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, virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const; MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering (default implementation: don't render anything). ///< Add reference into a cell for rendering (default implementation: don't render anything).

@ -21,17 +21,22 @@ namespace MWMechanics
class MechanicsManager; class MechanicsManager;
} }
namespace MWDialogue
{
class DialogueManager;
}
namespace MWWorld namespace MWWorld
{ {
class World; class World;
///< Collection of script-accessable sub-systems ///< Collection of script-accessable sub-systems
class Environment class Environment
{ {
public: public:
Environment() Environment()
: mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0),
mMechanicsManager (0), mFrameDuration (0) mMechanicsManager (0), mDialogueManager (0), mFrameDuration (0)
{} {}
World *mWorld; World *mWorld;
@ -39,9 +44,9 @@ namespace MWWorld
MWScript::GlobalScripts *mGlobalScripts; MWScript::GlobalScripts *mGlobalScripts;
MWGui::WindowManager *mWindowManager; MWGui::WindowManager *mWindowManager;
MWMechanics::MechanicsManager *mMechanicsManager; MWMechanics::MechanicsManager *mMechanicsManager;
MWDialogue::DialogueManager *mDialogueManager;
float mFrameDuration; float mFrameDuration;
}; };
} }
#endif #endif

@ -1,7 +1,10 @@
#ifndef _ESM_DIAL_H #ifndef _ESM_DIAL_H
#define _ESM_DIAL_H #define _ESM_DIAL_H
#include <vector>
#include "esm_reader.hpp" #include "esm_reader.hpp"
#include "loadinfo.hpp"
namespace ESM { namespace ESM {
@ -23,6 +26,7 @@ struct Dialogue
}; };
char type; char type;
std::vector<DialInfo> mInfo;
void load(ESMReader &esm) void load(ESMReader &esm)
{ {

@ -14,13 +14,13 @@
#include "loadcont.hpp" #include "loadcont.hpp"
#include "loadcrea.hpp" #include "loadcrea.hpp"
#include "loadcrec.hpp" #include "loadcrec.hpp"
#include "loadinfo.hpp"
#include "loaddial.hpp" #include "loaddial.hpp"
#include "loaddoor.hpp" #include "loaddoor.hpp"
#include "loadench.hpp" #include "loadench.hpp"
#include "loadfact.hpp" #include "loadfact.hpp"
#include "loadglob.hpp" #include "loadglob.hpp"
#include "loadgmst.hpp" #include "loadgmst.hpp"
#include "loadinfo.hpp"
#include "loadingr.hpp" #include "loadingr.hpp"
#include "loadland.hpp" #include "loadland.hpp"
#include "loadlevlist.hpp" #include "loadlevlist.hpp"

@ -18,32 +18,70 @@ static string toStr(int i)
void ESMStore::load(ESMReader &esm) void ESMStore::load(ESMReader &esm)
{ {
set<string> missing; set<string> missing;
// Loop through all records ESM::Dialogue *dialogue = 0;
while(esm.hasMoreRecs())
// Loop through all records
while(esm.hasMoreRecs())
{ {
NAME n = esm.getRecName(); NAME n = esm.getRecName();
esm.getRecHeader(); esm.getRecHeader();
// Look up the record type. // Look up the record type.
RecListList::iterator it = recLists.find(n.val); RecListList::iterator it = recLists.find(n.val);
if(it == recLists.end()) if(it == recLists.end())
{ {
// Not found (this would be an error later) if (n.val==ESM::REC_INFO)
esm.skipRecord(); {
missing.insert(n.toString()); if (dialogue)
continue; {
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<Dialogue>& recList = static_cast<RecListT<Dialogue>& > (*it->second);
// Load it id = recList.toLower (id);
std::string id = esm.getHNOString("NAME");
it->second->load(esm, id);
// Insert the reference into the global lookup RecListT<Dialogue>::MapType::iterator iter = recList.list.find (id);
if(!id.empty())
all[id] = n.val; 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 /* This information isn't needed on screen. But keep the code around

@ -69,7 +69,6 @@ namespace ESMS
// Lists that need special rules // Lists that need special rules
CellList cells; CellList cells;
RecIDListT<GameSetting> gameSettings; RecIDListT<GameSetting> gameSettings;
//RecListT<DialInfo> dialInfos;
//RecListT<Land> lands; //RecListT<Land> lands;
//RecListT<LandTexture> landTexts; //RecListT<LandTexture> landTexts;
//RecListT<MagicEffect> magicEffects; //RecListT<MagicEffect> magicEffects;
@ -92,7 +91,6 @@ namespace ESMS
ESMStore() ESMStore()
{ {
recLists[REC_ACTI] = &activators;
recLists[REC_ACTI] = &activators; recLists[REC_ACTI] = &activators;
recLists[REC_ALCH] = &potions; recLists[REC_ALCH] = &potions;
recLists[REC_APPA] = &appas; recLists[REC_APPA] = &appas;
@ -113,7 +111,6 @@ namespace ESMS
recLists[REC_FACT] = &factions; recLists[REC_FACT] = &factions;
recLists[REC_GLOB] = &globals; recLists[REC_GLOB] = &globals;
recLists[REC_GMST] = &gameSettings; recLists[REC_GMST] = &gameSettings;
//recLists[REC_INFO] = &dialInfos;
recLists[REC_INGR] = &ingreds; recLists[REC_INGR] = &ingreds;
//recLists[REC_LAND] = &lands; //recLists[REC_LAND] = &lands;
recLists[REC_LEVC] = &creatureLists; recLists[REC_LEVC] = &creatureLists;

@ -1 +1 @@
Subproject commit cd4ed4e6bfb23d736c4b1f30d6096ec164ba937b Subproject commit 200fab03efaa2cbe1b8fce4a742b0195f8912295
Loading…
Cancel
Save