From 083b11c74058523fe9dbb5098862d39177f932c3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 18 Jul 2010 16:48:01 +0200 Subject: [PATCH] moved global variable handling into a separate class --- apps/openmw/CMakeLists.txt | 5 +- apps/openmw/mwscript/interpretercontext.cpp | 22 +-- apps/openmw/mwworld/globals.cpp | 149 ++++++++++++++++++++ apps/openmw/mwworld/globals.hpp | 59 ++++++++ apps/openmw/mwworld/world.cpp | 21 +-- apps/openmw/mwworld/world.hpp | 7 +- 6 files changed, 227 insertions(+), 36 deletions(-) create mode 100644 apps/openmw/mwworld/globals.cpp create mode 100644 apps/openmw/mwworld/globals.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 4c1bedb491..8ffe9921f6 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -62,12 +62,15 @@ set(GAMESOUND_HEADER source_group(apps\\openmw\\mwsound FILES ${GAMESOUND} ${GAMESOUND_HEADER}) set(GAMEWORLD - mwworld/world.cpp) + mwworld/world.cpp + mwworld/globals.cpp + ) set(GAMEWORLD_HEADER mwworld/refdata.hpp mwworld/world.hpp mwworld/ptr.hpp mwworld/environment.hpp + mwworld/globals.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index c5cf436e59..eb0f90deb2 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -117,44 +117,34 @@ namespace MWScript int InterpreterContext::getGlobalShort (const std::string& name) const { - Interpreter::Type_Data value = mEnvironment.mWorld->getGlobalVariable (name); - return static_cast ( - *reinterpret_cast (&value)); + return mEnvironment.mWorld->getGlobalVariable (name).mShort; } int InterpreterContext::getGlobalLong (const std::string& name) const { // a global long is internally a float. - Interpreter::Type_Data value = mEnvironment.mWorld->getGlobalVariable (name); - return static_cast ( - *reinterpret_cast (&value)); + return mEnvironment.mWorld->getGlobalVariable (name).mLong; } float InterpreterContext::getGlobalFloat (const std::string& name) const { - Interpreter::Type_Data value = mEnvironment.mWorld->getGlobalVariable (name); - return *reinterpret_cast (&value); + return mEnvironment.mWorld->getGlobalVariable (name).mFloat; } void InterpreterContext::setGlobalShort (const std::string& name, int value) { - mEnvironment.mWorld->getGlobalVariable (name) = - *reinterpret_cast (&value); + mEnvironment.mWorld->getGlobalVariable (name).mShort = value; } void InterpreterContext::setGlobalLong (const std::string& name, int value) { // a global long is internally a float. - float value2 = float(value); - - mEnvironment.mWorld->getGlobalVariable (name) = - *reinterpret_cast (&value2); + mEnvironment.mWorld->getGlobalVariable (name).mLong = value; } void InterpreterContext::setGlobalFloat (const std::string& name, float value) { - mEnvironment.mWorld->getGlobalVariable (name) = - *reinterpret_cast (&value); + mEnvironment.mWorld->getGlobalVariable (name).mFloat = value; } bool InterpreterContext::isScriptRunning (const std::string& name) const diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp new file mode 100644 index 0000000000..6a45a51ece --- /dev/null +++ b/apps/openmw/mwworld/globals.cpp @@ -0,0 +1,149 @@ + +#include "globals.hpp" + +#include + +#include + +namespace MWWorld +{ + Globals::Collection::const_iterator Globals::find (const std::string& name) const + { + Collection::const_iterator iter = mVariables.find (name); + + if (iter==mVariables.end()) + throw std::runtime_error ("unknown global variable: " + name); + + return iter; + } + + Globals::Collection::iterator Globals::find (const std::string& name) + { + Collection::iterator iter = mVariables.find (name); + + if (iter==mVariables.end()) + throw std::runtime_error ("unknown global variable: " + name); + + return iter; + } + + Globals::Globals (const ESMS::ESMStore& store) + { + for (ESMS::RecListT::MapType::const_iterator iter + (store.globals.list.begin()); iter != store.globals.list.end(); ++iter) + { + char type = ' '; + Data value; + + switch (iter->second.type) + { + case ESM::VT_Short: + + type = 's'; + value.mShort = *reinterpret_cast ( + &iter->second.value); + break; + + case ESM::VT_Int: + + type = 'l'; + value.mLong = *reinterpret_cast ( + &iter->second.value); + break; + + case ESM::VT_Float: + + type = 'f'; + value.mFloat = *reinterpret_cast ( + &iter->second.value); + break; + + default: + + throw std::runtime_error ("unsupported global variable type"); + } + + mVariables.insert (std::make_pair (iter->first, std::make_pair (type, value))); + } + + if (mVariables.find ("dayspassed")==mVariables.end()) + { + // vanilla Morrowind does not define dayspassed. + Data value; + value.mLong = 0; + + mVariables.insert (std::make_pair ("dayspassed", std::make_pair ('l', value))); + } + } + + const Globals::Data& Globals::operator[] (const std::string& name) const + { + Collection::const_iterator iter = find (name); + + return iter->second.second; + } + + Globals::Data& Globals::operator[] (const std::string& name) + { + Collection::iterator iter = find (name); + + return iter->second.second; + } + + void Globals::setInt (const std::string& name, int value) + { + Collection::iterator iter = find (name); + + switch (iter->second.first) + { + case 's': iter->second.second.mShort = value; break; + case 'l': iter->second.second.mLong = value; break; + case 'f': iter->second.second.mFloat = value; break; + + default: throw std::runtime_error ("unsupported global variable type"); + } + } + + void Globals::setFloat (const std::string& name, float value) + { + Collection::iterator iter = find (name); + + switch (iter->second.first) + { + case 's': iter->second.second.mShort = value; break; + case 'l': iter->second.second.mLong = value; break; + case 'f': iter->second.second.mFloat = value; break; + + default: throw std::runtime_error ("unsupported global variable type"); + } + } + + int Globals::getInt (const std::string& name) const + { + Collection::const_iterator iter = find (name); + + switch (iter->second.first) + { + case 's': return iter->second.second.mShort; + case 'l': return iter->second.second.mLong; + case 'f': return iter->second.second.mFloat; + + default: throw std::runtime_error ("unsupported global variable type"); + } + } + + float Globals::getFloat (const std::string& name) const + { + Collection::const_iterator iter = find (name); + + switch (iter->second.first) + { + case 's': return iter->second.second.mShort; + case 'l': return iter->second.second.mLong; + case 'f': return iter->second.second.mFloat; + + default: throw std::runtime_error ("unsupported global variable type"); + } + } +} + diff --git a/apps/openmw/mwworld/globals.hpp b/apps/openmw/mwworld/globals.hpp new file mode 100644 index 0000000000..96ec3f3ce8 --- /dev/null +++ b/apps/openmw/mwworld/globals.hpp @@ -0,0 +1,59 @@ +#ifndef GAME_MWWORLD_GLOBALS_H +#define GAME_MWWORLD_GLOBALS_H + +#include +#include + +#include + +namespace ESMS +{ + struct ESMStore; +} + +namespace MWWorld +{ + class Globals + { + public: + + union Data + { + Interpreter::Type_Float mFloat; + Interpreter::Type_Float mLong; // Why Morrowind, why? :( + Interpreter::Type_Integer mShort; + }; + + typedef std::map > Collection; + + private: + + Collection mVariables; // type, value + + Collection::const_iterator find (const std::string& name) const; + + Collection::iterator find (const std::string& name); + + public: + + Globals (const ESMS::ESMStore& store); + + const Data& operator[] (const std::string& name) const; + + Data& operator[] (const std::string& name); + + void setInt (const std::string& name, int value); + ///< Set value independently from real type. + + void setFloat (const std::string& name, float value); + ///< Set value independently from real type. + + int getInt (const std::string& name) const; + ///< Get value independently from real type. + + float getFloat (const std::string& name) const; + ///< Get value independently from real type. + }; +} + +#endif diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6a3318250d..14be609d8e 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -143,7 +143,7 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, const std::string& startCell, bool newGame) - : mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0) + : mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0), mGlobalVariables (0) { boost::filesystem::path masterPath (dataDir); masterPath /= master; @@ -162,17 +162,12 @@ namespace MWWorld mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player")); // global variables - for (ESMS::RecListT::MapType::const_iterator iter - (mStore.globals.list.begin()); - iter != mStore.globals.list.end(); ++iter) - mGlobalVariables.insert (std::make_pair (iter->first, iter->second.value)); + mGlobalVariables = new Globals (mStore); if (newGame) { // set new game mark - float newGameState = 1; - mGlobalVariables["chargenstate"] = - *reinterpret_cast (&newGameState); + mGlobalVariables->setInt ("chargenstate", 1); } // This connects the cell data with the rendering scene. @@ -203,6 +198,7 @@ namespace MWWorld delete mPlayerPos; delete mSkyManager; + delete mGlobalVariables; } MWRender::PlayerPos& World::getPlayerPos() @@ -226,14 +222,9 @@ namespace MWWorld return false; } - Interpreter::Type_Data& World::getGlobalVariable (const std::string& name) + Globals::Data& World::getGlobalVariable (const std::string& name) { - std::map::iterator iter = mGlobalVariables.find (name); - - if (iter==mGlobalVariables.end()) - throw std::runtime_error ("unknown global variable: " + name); - - return iter->second; + return (*mGlobalVariables)[name]; } Ptr World::getPtr (const std::string& name, bool activeOnly) diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 3a40d8da95..d58e254dab 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -8,13 +8,12 @@ #include -#include - #include "../mwrender/playerpos.hpp" #include "../mwrender/mwscene.hpp" #include "refdata.hpp" #include "ptr.hpp" +#include "globals.hpp" namespace Render { @@ -51,7 +50,7 @@ namespace MWWorld ESMS::ESMStore mStore; std::map mInteriors; ScriptList mLocalScripts; - std::map mGlobalVariables; + MWWorld::Globals *mGlobalVariables; // not implemented World (const World&); @@ -80,7 +79,7 @@ namespace MWWorld bool hasCellChanged() const; ///< Has the player moved to a different cell, since the last frame? - Interpreter::Type_Data& getGlobalVariable (const std::string& name); + Globals::Data& getGlobalVariable (const std::string& name); Ptr getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name.