mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 06:15:32 +00:00
Merge branch 'master' of https://github.com/OpenMW/openmw
This commit is contained in:
commit
45af34d189
92 changed files with 908 additions and 380 deletions
|
@ -74,9 +74,6 @@ option(BUILD_OPENCS "build OpenMW Construction Set" ON)
|
|||
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
||||
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF)
|
||||
|
||||
# Sound source selection
|
||||
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
||||
|
||||
# OS X deployment
|
||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||
|
||||
|
@ -138,32 +135,10 @@ set(OPENMW_LIBS ${OENGINE_ALL})
|
|||
set(OPENMW_LIBS_HEADER)
|
||||
|
||||
# Sound setup
|
||||
set(GOT_SOUND_INPUT 0)
|
||||
set(SOUND_INPUT_INCLUDES "")
|
||||
set(SOUND_INPUT_LIBRARY "")
|
||||
set(SOUND_DEFINE "")
|
||||
if (USE_FFMPEG)
|
||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
|
||||
find_package(FFmpeg)
|
||||
if (FFMPEG_FOUND)
|
||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIRS})
|
||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG)
|
||||
set(GOT_SOUND_INPUT 1)
|
||||
endif (FFMPEG_FOUND)
|
||||
endif (USE_FFMPEG)
|
||||
|
||||
if (NOT GOT_SOUND_INPUT)
|
||||
message(WARNING "--------------------")
|
||||
message(WARNING "Failed to find any sound input packages")
|
||||
message(WARNING "--------------------")
|
||||
endif (NOT GOT_SOUND_INPUT)
|
||||
|
||||
if (NOT FFMPEG_FOUND)
|
||||
message(WARNING "--------------------")
|
||||
message(WARNING "FFmpeg not found, video playback will be disabled")
|
||||
message(WARNING "--------------------")
|
||||
endif (NOT FFMPEG_FOUND)
|
||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
|
||||
find_package(FFmpeg REQUIRED)
|
||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
||||
|
||||
# TinyXML
|
||||
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
||||
|
|
|
@ -9,7 +9,7 @@ opencs_units (model/doc
|
|||
)
|
||||
|
||||
opencs_units_noqt (model/doc
|
||||
stage savingstate savingstages
|
||||
stage savingstate savingstages blacklist
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/doc
|
||||
|
|
|
@ -86,7 +86,11 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
|
||||
("resources", boost::program_options::value<std::string>()->default_value("resources"))
|
||||
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
|
||||
default_value(std::vector<std::string>(), "fallback-archive")->multitoken());
|
||||
default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
|
||||
("script-blacklist", boost::program_options::value<std::vector<std::string> >()->default_value(std::vector<std::string>(), "")
|
||||
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)")
|
||||
("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
|
||||
->default_value(true), "enable script blacklisting");
|
||||
|
||||
boost::program_options::notify(variables);
|
||||
|
||||
|
@ -97,6 +101,10 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
|
||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
|
||||
|
||||
if (variables["script-blacklist-use"].as<bool>())
|
||||
mDocumentManager.setBlacklistedScripts (
|
||||
variables["script-blacklist"].as<std::vector<std::string> >());
|
||||
|
||||
mFsStrict = variables["fs-strict"].as<bool>();
|
||||
|
||||
Files::PathContainer dataDirs, dataLocal;
|
||||
|
|
31
apps/opencs/model/doc/blacklist.cpp
Normal file
31
apps/opencs/model/doc/blacklist.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
#include "blacklist.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
bool CSMDoc::Blacklist::isBlacklisted (const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> >::const_iterator iter =
|
||||
mIds.find (id.getType());
|
||||
|
||||
if (iter==mIds.end())
|
||||
return false;
|
||||
|
||||
return std::binary_search (iter->second.begin(), iter->second.end(),
|
||||
Misc::StringUtils::lowerCase (id.getId()));
|
||||
}
|
||||
|
||||
void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
|
||||
const std::vector<std::string>& ids)
|
||||
{
|
||||
std::vector<std::string>& list = mIds[type];
|
||||
|
||||
int size = list.size();
|
||||
|
||||
list.resize (size+ids.size());
|
||||
|
||||
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
|
||||
std::sort (list.begin(), list.end());
|
||||
}
|
25
apps/opencs/model/doc/blacklist.hpp
Normal file
25
apps/opencs/model/doc/blacklist.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef CSM_DOC_BLACKLIST_H
|
||||
#define CSM_DOC_BLACKLIST_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
/// \brief ID blacklist sorted by UniversalId type
|
||||
class Blacklist
|
||||
{
|
||||
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> > mIds;
|
||||
|
||||
public:
|
||||
|
||||
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
|
||||
|
||||
void add (CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2205,9 +2205,10 @@ void CSMDoc::Document::createBase()
|
|||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager)
|
||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||
const std::vector<std::string>& blacklistedScripts)
|
||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
||||
mTools (mData), mResDir(resDir),
|
||||
mTools (*this), mResDir(resDir),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSaving (*this, mProjectPath, encoding)
|
||||
|
@ -2239,6 +2240,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
createBase();
|
||||
}
|
||||
|
||||
mBlacklist.add (CSMWorld::UniversalId::Type_Script, blacklistedScripts);
|
||||
|
||||
addOptionalGmsts();
|
||||
addOptionalGlobals();
|
||||
|
||||
|
@ -2358,6 +2361,13 @@ CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId&
|
|||
return mTools.getReport (id);
|
||||
}
|
||||
|
||||
bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id)
|
||||
const
|
||||
{
|
||||
return mBlacklist.isBlacklisted (id);
|
||||
}
|
||||
|
||||
|
||||
void CSMDoc::Document::progress (int current, int max, int type)
|
||||
{
|
||||
emit progress (current, max, type, 1, this);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "state.hpp"
|
||||
#include "saving.hpp"
|
||||
#include "blacklist.hpp"
|
||||
|
||||
class QAbstractItemModel;
|
||||
|
||||
|
@ -52,6 +53,7 @@ namespace CSMDoc
|
|||
boost::filesystem::path mProjectPath;
|
||||
Saving mSaving;
|
||||
boost::filesystem::path mResDir;
|
||||
Blacklist mBlacklist;
|
||||
|
||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
||||
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
||||
|
@ -78,7 +80,8 @@ namespace CSMDoc
|
|||
Document (const Files::ConfigurationManager& configuration,
|
||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager);
|
||||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||
const std::vector<std::string>& blacklistedScripts);
|
||||
|
||||
~Document();
|
||||
|
||||
|
@ -110,6 +113,8 @@ namespace CSMDoc
|
|||
CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id);
|
||||
///< The ownership of the returned report is not transferred.
|
||||
|
||||
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
|
||||
|
||||
signals:
|
||||
|
||||
void stateChanged (int state, CSMDoc::Document *document);
|
||||
|
|
|
@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager()
|
|||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||
bool new_)
|
||||
{
|
||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager);
|
||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
|
||||
mDocuments.push_back (document);
|
||||
|
||||
|
@ -85,6 +85,11 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
|
|||
mEncoding = encoding;
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::setBlacklistedScripts (const std::vector<std::string>& scriptIds)
|
||||
{
|
||||
mBlacklistedScripts = scriptIds;
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::listResources()
|
||||
{
|
||||
mResourcesManager.listResources();
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace CSMDoc
|
|||
Loader mLoader;
|
||||
ToUTF8::FromType mEncoding;
|
||||
CSMWorld::ResourcesManager mResourcesManager;
|
||||
std::vector<std::string> mBlacklistedScripts;
|
||||
|
||||
DocumentManager (const DocumentManager&);
|
||||
DocumentManager& operator= (const DocumentManager&);
|
||||
|
@ -53,6 +54,8 @@ namespace CSMDoc
|
|||
|
||||
void setEncoding (ToUTF8::FromType encoding);
|
||||
|
||||
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
|
||||
|
||||
/// Ask OGRE for a list of available resources.
|
||||
void listResources();
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <components/compiler/exception.hpp>
|
||||
#include <components/compiler/extensions0.hpp>
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
||||
|
@ -37,8 +39,8 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
|||
(type==ErrorMessage ? "error: " : "warning: ") + message));
|
||||
}
|
||||
|
||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
|
||||
: mData (data), mContext (data), mMessages (0)
|
||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
||||
: mDocument (document), mContext (document.getData()), mMessages (0)
|
||||
{
|
||||
/// \todo add an option to configure warning mode
|
||||
setWarningsMode (0);
|
||||
|
@ -53,18 +55,25 @@ int CSMTools::ScriptCheckStage::setup()
|
|||
mMessages = 0;
|
||||
mId.clear();
|
||||
|
||||
return mData.getScripts().getSize();
|
||||
return mDocument.getData().getScripts().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages)
|
||||
{
|
||||
mId = mDocument.getData().getScripts().getId (stage);
|
||||
|
||||
if (mDocument.isBlacklisted (
|
||||
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
|
||||
return;
|
||||
|
||||
mMessages = &messages;
|
||||
mId = mData.getScripts().getId (stage);
|
||||
|
||||
try
|
||||
{
|
||||
mFile = mData.getScripts().getRecord (stage).get().mId;
|
||||
std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText);
|
||||
const CSMWorld::Data& data = mDocument.getData();
|
||||
|
||||
mFile = data.getScripts().getRecord (stage).get().mId;
|
||||
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
|
||||
|
||||
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
||||
|
||||
|
|
|
@ -8,12 +8,17 @@
|
|||
|
||||
#include "../world/scriptcontext.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
/// \brief VerifyStage: make sure that scripts compile
|
||||
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
||||
{
|
||||
const CSMWorld::Data& mData;
|
||||
const CSMDoc::Document& mDocument;
|
||||
Compiler::Extensions mExtensions;
|
||||
CSMWorld::ScriptContext mContext;
|
||||
std::string mId;
|
||||
|
@ -28,7 +33,7 @@ namespace CSMTools
|
|||
|
||||
public:
|
||||
|
||||
ScriptCheckStage (const CSMWorld::Data& data);
|
||||
ScriptCheckStage (const CSMDoc::Document& document);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "../doc/state.hpp"
|
||||
#include "../doc/operation.hpp"
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
#include "../world/data.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
@ -80,13 +81,14 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
|||
|
||||
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
|
||||
|
||||
mVerifier->appendStage (new ScriptCheckStage (mData));
|
||||
mVerifier->appendStage (new ScriptCheckStage (mDocument));
|
||||
}
|
||||
|
||||
return mVerifier;
|
||||
}
|
||||
|
||||
CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0)
|
||||
CSMTools::Tools::Tools (CSMDoc::Document& document)
|
||||
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0)
|
||||
{
|
||||
// index 0: load error log
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace CSMWorld
|
|||
namespace CSMDoc
|
||||
{
|
||||
class Operation;
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSMTools
|
||||
|
@ -24,6 +25,7 @@ namespace CSMTools
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMDoc::Document& mDocument;
|
||||
CSMWorld::Data& mData;
|
||||
CSMDoc::Operation *mVerifier;
|
||||
std::map<int, ReportModel *> mReports;
|
||||
|
@ -44,7 +46,7 @@ namespace CSMTools
|
|||
|
||||
public:
|
||||
|
||||
Tools (CSMWorld::Data& data);
|
||||
Tools (CSMDoc::Document& document);
|
||||
|
||||
virtual ~Tools();
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ add_executable(openmw
|
|||
# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
|
||||
# when we change the backend.
|
||||
include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS})
|
||||
add_definitions(${SOUND_DEFINE})
|
||||
|
||||
target_link_libraries(openmw
|
||||
${OGRE_LIBRARIES}
|
||||
|
|
|
@ -180,6 +180,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
|||
, mEncoder(NULL)
|
||||
, mActivationDistanceOverride(-1)
|
||||
, mGrab(true)
|
||||
, mScriptBlacklistUse (true)
|
||||
|
||||
{
|
||||
std::srand ( std::time(NULL) );
|
||||
|
@ -406,7 +407,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
mScriptContext->setExtensions (&mExtensions);
|
||||
|
||||
mEnvironment.setScriptManager (new MWScript::ScriptManager (MWBase::Environment::get().getWorld()->getStore(),
|
||||
mVerboseScripts, *mScriptContext, mWarningsMode));
|
||||
mVerboseScripts, *mScriptContext, mWarningsMode,
|
||||
mScriptBlacklistUse ? mScriptBlacklist : std::vector<std::string>()));
|
||||
|
||||
// Create game mechanics system
|
||||
MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager;
|
||||
|
@ -565,3 +567,13 @@ void OMW::Engine::setWarningsMode (int mode)
|
|||
{
|
||||
mWarningsMode = mode;
|
||||
}
|
||||
|
||||
void OMW::Engine::setScriptBlacklist (const std::vector<std::string>& list)
|
||||
{
|
||||
mScriptBlacklist = list;
|
||||
}
|
||||
|
||||
void OMW::Engine::setScriptBlacklistUse (bool use)
|
||||
{
|
||||
mScriptBlacklistUse = use;
|
||||
}
|
|
@ -89,6 +89,8 @@ namespace OMW
|
|||
Files::Collections mFileCollections;
|
||||
bool mFSStrict;
|
||||
Translation::Storage mTranslationDataStorage;
|
||||
std::vector<std::string> mScriptBlacklist;
|
||||
bool mScriptBlacklistUse;
|
||||
|
||||
// not implemented
|
||||
Engine (const Engine&);
|
||||
|
@ -181,6 +183,10 @@ namespace OMW
|
|||
|
||||
void setWarningsMode (int mode);
|
||||
|
||||
void setScriptBlacklist (const std::vector<std::string>& list);
|
||||
|
||||
void setScriptBlacklistUse (bool use);
|
||||
|
||||
private:
|
||||
Files::ConfigurationManager& mCfgMgr;
|
||||
};
|
||||
|
|
|
@ -144,6 +144,12 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
"\t1 - show warning but consider script as correctly compiled anyway\n"
|
||||
"\t2 - treat warnings as errors")
|
||||
|
||||
("script-blacklist", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
||||
->multitoken(), "ignore the specified script (if the use of the blacklist is enabled)")
|
||||
|
||||
("script-blacklist-use", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(true), "enable script blacklisting")
|
||||
|
||||
("skip-menu", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "skip main menu on game startup")
|
||||
|
||||
|
@ -184,6 +190,14 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
if (variables.count ("version"))
|
||||
{
|
||||
std::cout << "OpenMW version " << OPENMW_VERSION << std::endl;
|
||||
|
||||
std::string rev = OPENMW_VERSION_COMMITHASH;
|
||||
std::string tag = OPENMW_VERSION_TAGHASH;
|
||||
if (!rev.empty() && !tag.empty())
|
||||
{
|
||||
rev = rev.substr(0, 10);
|
||||
std::cout << "Revision " << rev << std::endl;
|
||||
}
|
||||
run = false;
|
||||
}
|
||||
|
||||
|
@ -241,15 +255,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
engine.setCell(variables["start"].as<std::string>());
|
||||
engine.setSkipMenu (variables["skip-menu"].as<bool>());
|
||||
|
||||
// other settings
|
||||
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
||||
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
|
||||
// scripts
|
||||
engine.setCompileAll(variables["script-all"].as<bool>());
|
||||
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
|
||||
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
|
||||
engine.setScriptConsoleMode (variables["script-console"].as<bool>());
|
||||
engine.setStartupScript (variables["script-run"].as<std::string>());
|
||||
engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
|
||||
engine.setWarningsMode (variables["script-warn"].as<int>());
|
||||
engine.setScriptBlacklist (variables["script-blacklist"].as<StringsVector>());
|
||||
engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>());
|
||||
|
||||
// other settings
|
||||
engine.setSoundUsage(!variables["no-sound"].as<bool>());
|
||||
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
|
||||
engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -46,17 +46,11 @@ namespace MWBase
|
|||
///< Compile all scripts
|
||||
/// \return count, success
|
||||
|
||||
virtual Compiler::Locals& getLocals (const std::string& name) = 0;
|
||||
virtual const Compiler::Locals& getLocals (const std::string& name) = 0;
|
||||
///< Return locals for script \a name.
|
||||
|
||||
virtual MWScript::GlobalScripts& getGlobalScripts() = 0;
|
||||
|
||||
virtual int getLocalIndex (const std::string& scriptId, const std::string& variable,
|
||||
char type) = 0;
|
||||
///< Return index of the variable of the given name and type in the given script. Will
|
||||
/// throw an exception, if there is no such script or variable or the type does not match.
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Activator::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Activator>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -13,6 +13,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Apparatus::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Apparatus>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -13,6 +13,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Armor::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Armor>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Book::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Book>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Clothing::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Clothing>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -43,6 +43,11 @@ namespace
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Container::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Container>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Container::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
|
|
|
@ -15,6 +15,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -27,6 +27,11 @@ namespace
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string CreatureLevList::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::CreatureLevList>()->mBase->mId;
|
||||
}
|
||||
|
||||
std::string CreatureLevList::getName (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return "";
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
||||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
|
|
@ -42,6 +42,11 @@ namespace
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Door::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Door>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -16,6 +16,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string ItemLevList::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::ItemLevList>()->mBase->mId;
|
||||
}
|
||||
|
||||
std::string ItemLevList::getName (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return "";
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace MWClass
|
|||
{
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
||||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
|
|
@ -47,6 +47,11 @@ namespace
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Light::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Light>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -14,6 +14,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Lockpick::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Lockpick>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -38,6 +38,11 @@ bool isGold (const MWWorld::Ptr& ptr)
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Miscellaneous::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Miscellaneous>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Potion::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Potion>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Probe::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Probe>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Repair::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Repair>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
const std::string model = getModel(ptr);
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Static::getId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Static>()->mBase->mId;
|
||||
}
|
||||
|
||||
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Static> *ref =
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace MWClass
|
|||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
|
||||
#include "filter.hpp"
|
||||
|
||||
#include <components/compiler/locals.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
@ -197,33 +200,28 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
|
|||
if (scriptName.empty())
|
||||
return false; // no script
|
||||
|
||||
const ESM::Script *script =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName);
|
||||
std::string name = Misc::StringUtils::lowerCase (select.getName());
|
||||
|
||||
std::string name = select.getName();
|
||||
const Compiler::Locals& localDefs =
|
||||
MWBase::Environment::get().getScriptManager()->getLocals (scriptName);
|
||||
|
||||
int i = 0;
|
||||
char type = localDefs.getType (name);
|
||||
|
||||
for (; i<static_cast<int> (script->mVarNames.size()); ++i)
|
||||
if (Misc::StringUtils::ciEqual(script->mVarNames[i], name))
|
||||
break;
|
||||
if (type==' ')
|
||||
return false; // script does not have a variable of this name.
|
||||
|
||||
if (i>=static_cast<int> (script->mVarNames.size()))
|
||||
return false; // script does not have a variable of this name
|
||||
int index = localDefs.getIndex (name);
|
||||
|
||||
const MWScript::Locals& locals = mActor.getRefData().getLocals();
|
||||
|
||||
if (i<script->mData.mNumShorts)
|
||||
return select.selectCompare (static_cast<int> (locals.mShorts[i]));
|
||||
switch (type)
|
||||
{
|
||||
case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
|
||||
case 'l': return select.selectCompare (locals.mLongs[index]);
|
||||
case 'f': return select.selectCompare (locals.mFloats[index]);
|
||||
}
|
||||
|
||||
i -= script->mData.mNumShorts;
|
||||
|
||||
if (i<script->mData.mNumLongs)
|
||||
return select.selectCompare (locals.mLongs[i]);
|
||||
|
||||
i -= script->mData.mNumLongs;
|
||||
|
||||
return select.selectCompare (locals.mFloats.at (i));
|
||||
throw std::logic_error ("unknown local variable type in dialogue filter");
|
||||
}
|
||||
|
||||
case SelectWrapper::Function_PcHealthPercent:
|
||||
|
@ -463,20 +461,10 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
|||
// This actor has no attached script, so there is no local variable
|
||||
return true;
|
||||
|
||||
const ESM::Script *script =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName);
|
||||
const Compiler::Locals& localDefs =
|
||||
MWBase::Environment::get().getScriptManager()->getLocals (scriptName);
|
||||
|
||||
std::string name = select.getName();
|
||||
|
||||
int i = 0;
|
||||
for (; i < static_cast<int> (script->mVarNames.size()); ++i)
|
||||
if (Misc::StringUtils::ciEqual(script->mVarNames[i], name))
|
||||
break;
|
||||
|
||||
if (i >= static_cast<int> (script->mVarNames.size()))
|
||||
return true; // script does not have a variable of this name
|
||||
|
||||
return false;
|
||||
return localDefs.getIndex (Misc::StringUtils::lowerCase (select.getName()))==-1;
|
||||
}
|
||||
|
||||
case SelectWrapper::Function_SameGender:
|
||||
|
|
|
@ -22,6 +22,9 @@ namespace MWMechanics
|
|||
{
|
||||
static const int COUNT_BEFORE_RESET = 200; // TODO: maybe no longer needed
|
||||
static const float DOOR_CHECK_INTERVAL = 1.5f;
|
||||
static const float REACTION_INTERVAL = 0.25f;
|
||||
static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player
|
||||
static const int GREETING_SHOULD_END = 10;
|
||||
|
||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
||||
|
@ -43,7 +46,8 @@ namespace MWMechanics
|
|||
mReaction = 0;
|
||||
mRotate = false;
|
||||
mTargetAngle = 0;
|
||||
mSaidGreeting = false;
|
||||
mSaidGreeting = Greet_None;
|
||||
greetingTimer = 0;
|
||||
mHasReturnPosition = false;
|
||||
mReturnPosition = Ogre::Vector3(0,0,0);
|
||||
|
||||
|
@ -221,14 +225,14 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
mReaction += duration;
|
||||
if(mReaction < 0.25f) // FIXME: hard coded constant
|
||||
if(mReaction < REACTION_INTERVAL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
mReaction = 0;
|
||||
|
||||
// NOTE: everything below get updated every 0.25 seconds
|
||||
// NOTE: everything below get updated every REACTION_INTERVAL seconds
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
if(mDuration)
|
||||
|
@ -407,7 +411,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
// Allow interrupting a walking actor to trigger a greeting
|
||||
if(mIdleNow || (mWalking && !mObstacleCheck.isNormalState() && mDistance))
|
||||
if(mIdleNow || mWalking)
|
||||
{
|
||||
// Play a random voice greeting if the player gets too close
|
||||
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
||||
|
@ -421,9 +425,25 @@ namespace MWMechanics
|
|||
Ogre::Vector3 playerPos(player.getRefData().getPosition().pos);
|
||||
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
|
||||
float playerDistSqr = playerPos.squaredDistance(actorPos);
|
||||
|
||||
if(playerDistSqr <= helloDistance*helloDistance)
|
||||
|
||||
if (mSaidGreeting == Greet_None)
|
||||
{
|
||||
if (playerDistSqr <= helloDistance*helloDistance)
|
||||
greetingTimer++;
|
||||
|
||||
// TODO: check if actor is aware / has line of sight
|
||||
if (greetingTimer >= GREETING_SHOULD_START)
|
||||
{
|
||||
mSaidGreeting = Greet_InProgress;
|
||||
MWBase::Environment::get().getDialogueManager()->say(actor, "hello");
|
||||
greetingTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(mSaidGreeting == Greet_InProgress)
|
||||
{
|
||||
greetingTimer++;
|
||||
|
||||
if(mWalking)
|
||||
{
|
||||
stopWalking(actor);
|
||||
|
@ -449,31 +469,25 @@ namespace MWMechanics
|
|||
mRotate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mSaidGreeting)
|
||||
{
|
||||
// TODO: check if actor is aware / has line of sight
|
||||
if (playerDistSqr <= helloDistance*helloDistance
|
||||
// Only play a greeting if the player is not moving
|
||||
&& Ogre::Vector3(player.getClass().getMovementSettings(player).mPosition).squaredLength() == 0)
|
||||
|
||||
if (greetingTimer >= GREETING_SHOULD_END)
|
||||
{
|
||||
mSaidGreeting = true;
|
||||
MWBase::Environment::get().getDialogueManager()->say(actor, "hello");
|
||||
mSaidGreeting = Greet_Done;
|
||||
greetingTimer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (mSaidGreeting == MWMechanics::AiWander::Greet_Done)
|
||||
{
|
||||
static float fGreetDistanceReset = MWBase::Environment::get().getWorld()->getStore()
|
||||
.get<ESM::GameSetting>().find("fGreetDistanceReset")->getFloat();
|
||||
|
||||
if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset * iGreetDistanceMultiplier*iGreetDistanceMultiplier)
|
||||
mSaidGreeting = false;
|
||||
if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset)
|
||||
mSaidGreeting = Greet_None;
|
||||
}
|
||||
|
||||
// Check if idle animation finished
|
||||
// FIXME: don't stay forever
|
||||
if(!checkIdle(actor, mPlayedIdle) && playerDistSqr > helloDistance*helloDistance)
|
||||
if(!checkIdle(actor, mPlayedIdle) && (playerDistSqr > helloDistance*helloDistance || mSaidGreeting == MWMechanics::AiWander::Greet_Done))
|
||||
{
|
||||
mPlayedIdle = 0;
|
||||
mIdleNow = false;
|
||||
|
|
|
@ -62,7 +62,13 @@ namespace MWMechanics
|
|||
std::vector<unsigned char> mIdle;
|
||||
bool mRepeat;
|
||||
|
||||
bool mSaidGreeting;
|
||||
enum GreetingState {
|
||||
Greet_None,
|
||||
Greet_InProgress,
|
||||
Greet_Done
|
||||
};
|
||||
GreetingState mSaidGreeting;
|
||||
int greetingTimer;
|
||||
|
||||
bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position,
|
||||
// if we had the actor in the AiWander constructor...
|
||||
|
|
|
@ -26,8 +26,6 @@ typedef SSIZE_T ssize_t;
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
#ifdef OPENMW_USE_FFMPEG
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
@ -1073,27 +1071,6 @@ void VideoState::deinit()
|
|||
}
|
||||
}
|
||||
|
||||
#else // defined OPENMW_USE_FFMPEG
|
||||
|
||||
class VideoState
|
||||
{
|
||||
public:
|
||||
VideoState() { }
|
||||
|
||||
void init(const std::string& resourceName)
|
||||
{
|
||||
throw std::runtime_error("FFmpeg not supported, cannot play \""+resourceName+"\"");
|
||||
}
|
||||
void deinit() { }
|
||||
|
||||
void close() { }
|
||||
|
||||
bool update()
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
#endif // defined OPENMW_USE_FFMPEG
|
||||
|
||||
|
||||
VideoPlayer::VideoPlayer()
|
||||
: mState(NULL)
|
||||
|
|
|
@ -15,61 +15,69 @@
|
|||
|
||||
namespace MWScript
|
||||
{
|
||||
GlobalScriptDesc::GlobalScriptDesc() : mRunning (false) {}
|
||||
|
||||
|
||||
GlobalScripts::GlobalScripts (const MWWorld::ESMStore& store)
|
||||
: mStore (store)
|
||||
{
|
||||
addStartup();
|
||||
}
|
||||
{}
|
||||
|
||||
void GlobalScripts::addScript (const std::string& name)
|
||||
void GlobalScripts::addScript (const std::string& name, const std::string& targetId)
|
||||
{
|
||||
std::map<std::string, std::pair<bool, Locals> >::iterator iter =
|
||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||
|
||||
if (iter==mScripts.end())
|
||||
{
|
||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
|
||||
{
|
||||
Locals locals;
|
||||
GlobalScriptDesc desc;
|
||||
desc.mRunning = true;
|
||||
desc.mLocals.configure (*script);
|
||||
desc.mId = targetId;
|
||||
|
||||
locals.configure (*script);
|
||||
|
||||
mScripts.insert (std::make_pair (name, std::make_pair (true, locals)));
|
||||
mScripts.insert (std::make_pair (name, desc));
|
||||
}
|
||||
}
|
||||
else
|
||||
iter->second.first = true;
|
||||
else if (!iter->second.mRunning)
|
||||
{
|
||||
iter->second.mRunning = true;
|
||||
iter->second.mId = targetId;
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalScripts::removeScript (const std::string& name)
|
||||
{
|
||||
std::map<std::string, std::pair<bool, Locals> >::iterator iter =
|
||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||
|
||||
if (iter!=mScripts.end())
|
||||
iter->second.first = false;
|
||||
iter->second.mRunning = false;
|
||||
}
|
||||
|
||||
bool GlobalScripts::isRunning (const std::string& name) const
|
||||
{
|
||||
std::map<std::string, std::pair<bool, Locals> >::const_iterator iter =
|
||||
std::map<std::string, GlobalScriptDesc>::const_iterator iter =
|
||||
mScripts.find (::Misc::StringUtils::lowerCase (name));
|
||||
|
||||
if (iter==mScripts.end())
|
||||
return false;
|
||||
|
||||
return iter->second.first;
|
||||
return iter->second.mRunning;
|
||||
}
|
||||
|
||||
void GlobalScripts::run()
|
||||
{
|
||||
for (std::map<std::string, std::pair<bool, Locals> >::iterator iter (mScripts.begin());
|
||||
for (std::map<std::string, GlobalScriptDesc>::iterator iter (mScripts.begin());
|
||||
iter!=mScripts.end(); ++iter)
|
||||
{
|
||||
if (iter->second.first)
|
||||
if (iter->second.mRunning)
|
||||
{
|
||||
MWWorld::Ptr ptr;
|
||||
|
||||
MWScript::InterpreterContext interpreterContext (
|
||||
&iter->second.second, MWWorld::Ptr());
|
||||
&iter->second.mLocals, MWWorld::Ptr(), iter->second.mId);
|
||||
|
||||
MWBase::Environment::get().getScriptManager()->run (iter->first, interpreterContext);
|
||||
}
|
||||
}
|
||||
|
@ -99,16 +107,18 @@ namespace MWScript
|
|||
|
||||
void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||
{
|
||||
for (std::map<std::string, std::pair<bool, Locals> >::const_iterator iter (mScripts.begin());
|
||||
for (std::map<std::string, GlobalScriptDesc>::const_iterator iter (mScripts.begin());
|
||||
iter!=mScripts.end(); ++iter)
|
||||
{
|
||||
ESM::GlobalScript script;
|
||||
|
||||
script.mId = iter->first;
|
||||
|
||||
iter->second.second.write (script.mLocals, iter->first);
|
||||
iter->second.mLocals.write (script.mLocals, iter->first);
|
||||
|
||||
script.mRunning = iter->second.first ? 1 : 0;
|
||||
script.mRunning = iter->second.mRunning ? 1 : 0;
|
||||
|
||||
script.mTargetId = iter->second.mId;
|
||||
|
||||
writer.startRecord (ESM::REC_GSCR);
|
||||
script.save (writer);
|
||||
|
@ -124,25 +134,25 @@ namespace MWScript
|
|||
ESM::GlobalScript script;
|
||||
script.load (reader);
|
||||
|
||||
std::map<std::string, std::pair<bool, Locals> >::iterator iter =
|
||||
std::map<std::string, GlobalScriptDesc>::iterator iter =
|
||||
mScripts.find (script.mId);
|
||||
|
||||
if (iter==mScripts.end())
|
||||
{
|
||||
if (const ESM::Script *scriptRecord = mStore.get<ESM::Script>().search (script.mId))
|
||||
{
|
||||
std::pair<bool, Locals> data (false, Locals());
|
||||
GlobalScriptDesc desc;
|
||||
desc.mLocals.configure (*scriptRecord);
|
||||
|
||||
data.second.configure (*scriptRecord);
|
||||
|
||||
iter = mScripts.insert (std::make_pair (script.mId, data)).first;
|
||||
iter = mScripts.insert (std::make_pair (script.mId, desc)).first;
|
||||
}
|
||||
else // script does not exist anymore
|
||||
return true;
|
||||
}
|
||||
|
||||
iter->second.first = script.mRunning!=0;
|
||||
iter->second.second.read (script.mLocals, script.mId);
|
||||
iter->second.mRunning = script.mRunning!=0;
|
||||
iter->second.mLocals.read (script.mLocals, script.mId);
|
||||
iter->second.mId = script.mTargetId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -153,21 +163,19 @@ namespace MWScript
|
|||
Locals& GlobalScripts::getLocals (const std::string& name)
|
||||
{
|
||||
std::string name2 = ::Misc::StringUtils::lowerCase (name);
|
||||
std::map<std::string, std::pair<bool, Locals> >::iterator iter =
|
||||
mScripts.find (name2);
|
||||
std::map<std::string, GlobalScriptDesc>::iterator iter = mScripts.find (name2);
|
||||
|
||||
if (iter==mScripts.end())
|
||||
{
|
||||
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
|
||||
{
|
||||
Locals locals;
|
||||
GlobalScriptDesc desc;
|
||||
desc.mLocals.configure (*script);
|
||||
|
||||
locals.configure (*script);
|
||||
|
||||
iter = mScripts.insert (std::make_pair (name, std::make_pair (false, locals))).first;
|
||||
iter = mScripts.insert (std::make_pair (name, desc)).first;
|
||||
}
|
||||
}
|
||||
|
||||
return iter->second.second;
|
||||
return iter->second.mLocals;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,16 +26,25 @@ namespace MWWorld
|
|||
|
||||
namespace MWScript
|
||||
{
|
||||
struct GlobalScriptDesc
|
||||
{
|
||||
bool mRunning;
|
||||
Locals mLocals;
|
||||
std::string mId; // ID used to start targeted script (empty if not a targeted script)
|
||||
|
||||
GlobalScriptDesc();
|
||||
};
|
||||
|
||||
class GlobalScripts
|
||||
{
|
||||
const MWWorld::ESMStore& mStore;
|
||||
std::map<std::string, std::pair<bool, Locals> > mScripts; // running, local variables
|
||||
std::map<std::string, GlobalScriptDesc> mScripts;
|
||||
|
||||
public:
|
||||
|
||||
GlobalScripts (const MWWorld::ESMStore& store);
|
||||
|
||||
void addScript (const std::string& name);
|
||||
void addScript (const std::string& name, const std::string& targetId = "");
|
||||
|
||||
void removeScript (const std::string& name);
|
||||
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <components/interpreter/types.hpp>
|
||||
|
||||
#include <components/compiler/locals.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -22,7 +26,7 @@
|
|||
|
||||
namespace MWScript
|
||||
{
|
||||
MWWorld::Ptr InterpreterContext::getReference (
|
||||
MWWorld::Ptr InterpreterContext::getReferenceImp (
|
||||
const std::string& id, bool activeOnly, bool doThrow)
|
||||
{
|
||||
if (!id.empty())
|
||||
|
@ -31,6 +35,10 @@ namespace MWScript
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mReference.isEmpty() && !mTargetId.empty())
|
||||
mReference =
|
||||
MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false);
|
||||
|
||||
if (mReference.isEmpty() && doThrow)
|
||||
throw std::runtime_error ("no implicit reference");
|
||||
|
||||
|
@ -38,7 +46,7 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
|
||||
const MWWorld::Ptr InterpreterContext::getReference (
|
||||
const MWWorld::Ptr InterpreterContext::getReferenceImp (
|
||||
const std::string& id, bool activeOnly, bool doThrow) const
|
||||
{
|
||||
if (!id.empty())
|
||||
|
@ -47,6 +55,10 @@ namespace MWScript
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mReference.isEmpty() && !mTargetId.empty())
|
||||
mReference =
|
||||
MWBase::Environment::get().getWorld()->searchPtr (mTargetId, false);
|
||||
|
||||
if (mReference.isEmpty() && doThrow)
|
||||
throw std::runtime_error ("no implicit reference");
|
||||
|
||||
|
@ -64,7 +76,7 @@ namespace MWScript
|
|||
}
|
||||
else
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
const MWWorld::Ptr ptr = getReferenceImp (id, false);
|
||||
|
||||
id = ptr.getClass().getScript (ptr);
|
||||
|
||||
|
@ -84,7 +96,7 @@ namespace MWScript
|
|||
}
|
||||
else
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
const MWWorld::Ptr ptr = getReferenceImp (id, false);
|
||||
|
||||
id = ptr.getClass().getScript (ptr);
|
||||
|
||||
|
@ -95,11 +107,43 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
|
||||
int InterpreterContext::findLocalVariableIndex (const std::string& scriptId,
|
||||
const std::string& name, char type) const
|
||||
{
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocals (scriptId).
|
||||
search (type, name);
|
||||
|
||||
if (index!=-1)
|
||||
return index;
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "Failed to access ";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 's': stream << "short"; break;
|
||||
case 'l': stream << "long"; break;
|
||||
case 'f': stream << "float"; break;
|
||||
}
|
||||
|
||||
stream << " member variable " << name << " in script " << scriptId;
|
||||
|
||||
throw std::runtime_error (stream.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
InterpreterContext::InterpreterContext (
|
||||
MWScript::Locals *locals, MWWorld::Ptr reference)
|
||||
MWScript::Locals *locals, MWWorld::Ptr reference, const std::string& targetId)
|
||||
: mLocals (locals), mReference (reference),
|
||||
mActivationHandled (false)
|
||||
{}
|
||||
mActivationHandled (false), mTargetId (targetId)
|
||||
{
|
||||
// If we run on a reference (local script, dialogue script or console with object
|
||||
// selected), store the ID of that reference store it so it can be inherited by
|
||||
// targeted scripts started from this one.
|
||||
if (targetId.empty() && !reference.isEmpty())
|
||||
mTargetId = reference.getClass().getId (reference);
|
||||
}
|
||||
|
||||
int InterpreterContext::getLocalShort (int index) const
|
||||
{
|
||||
|
@ -236,34 +280,34 @@ namespace MWScript
|
|||
|
||||
std::string InterpreterContext::getNPCName() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
ESM::NPC npc = *getReferenceImp().get<ESM::NPC>()->mBase;
|
||||
return npc.mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCRace() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
ESM::NPC npc = *getReferenceImp().get<ESM::NPC>()->mBase;
|
||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc.mRace);
|
||||
return race->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCClass() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
ESM::NPC npc = *getReferenceImp().get<ESM::NPC>()->mBase;
|
||||
const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc.mClass);
|
||||
return class_->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCFaction() const
|
||||
{
|
||||
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
|
||||
ESM::NPC npc = *getReferenceImp().get<ESM::NPC>()->mBase;
|
||||
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npc.mFaction);
|
||||
return faction->mName;
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getNPCRank() const
|
||||
{
|
||||
std::map<std::string, int> ranks = mReference.getClass().getNpcStats (mReference).getFactionRanks();
|
||||
std::map<std::string, int> ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.begin();
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
|
@ -299,7 +343,7 @@ namespace MWScript
|
|||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr player = world->getPlayerPtr();
|
||||
|
||||
std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first;
|
||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||
|
||||
std::map<std::string, int> ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(factionId);
|
||||
|
@ -326,7 +370,7 @@ namespace MWScript
|
|||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr player = world->getPlayerPtr();
|
||||
|
||||
std::string factionId = mReference.getClass().getNpcStats (mReference).getFactionRanks().begin()->first;
|
||||
std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
|
||||
|
||||
std::map<std::string, int> ranks = player.getClass().getNpcStats (player).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator it = ranks.find(factionId);
|
||||
|
@ -366,9 +410,9 @@ namespace MWScript
|
|||
return MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name);
|
||||
}
|
||||
|
||||
void InterpreterContext::startScript (const std::string& name)
|
||||
void InterpreterContext::startScript (const std::string& name, const std::string& targetId)
|
||||
{
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name);
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, targetId);
|
||||
}
|
||||
|
||||
void InterpreterContext::stopScript (const std::string& name)
|
||||
|
@ -383,7 +427,7 @@ namespace MWScript
|
|||
MWWorld::Ptr ref2;
|
||||
|
||||
if (id.empty())
|
||||
ref2 = getReference("", true, true);
|
||||
ref2 = getReferenceImp();
|
||||
else
|
||||
ref2 = MWBase::Environment::get().getWorld()->searchPtr(id, true);
|
||||
|
||||
|
@ -448,19 +492,19 @@ namespace MWScript
|
|||
|
||||
bool InterpreterContext::isDisabled (const std::string& id) const
|
||||
{
|
||||
const MWWorld::Ptr ref = getReference (id, false);
|
||||
const MWWorld::Ptr ref = getReferenceImp (id, false);
|
||||
return !ref.getRefData().isEnabled();
|
||||
}
|
||||
|
||||
void InterpreterContext::enable (const std::string& id)
|
||||
{
|
||||
MWWorld::Ptr ref = getReference (id, false);
|
||||
MWWorld::Ptr ref = getReferenceImp (id, false);
|
||||
MWBase::Environment::get().getWorld()->enable (ref);
|
||||
}
|
||||
|
||||
void InterpreterContext::disable (const std::string& id)
|
||||
{
|
||||
MWWorld::Ptr ref = getReference (id, false);
|
||||
MWWorld::Ptr ref = getReferenceImp (id, false);
|
||||
MWBase::Environment::get().getWorld()->disable (ref);
|
||||
}
|
||||
|
||||
|
@ -471,10 +515,7 @@ namespace MWScript
|
|||
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 's');
|
||||
|
||||
return locals.mShorts[index];
|
||||
return locals.mShorts[findLocalVariableIndex (scriptId, name, 's')];
|
||||
}
|
||||
|
||||
int InterpreterContext::getMemberLong (const std::string& id, const std::string& name,
|
||||
|
@ -484,10 +525,7 @@ namespace MWScript
|
|||
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 'l');
|
||||
|
||||
return locals.mLongs[index];
|
||||
return locals.mLongs[findLocalVariableIndex (scriptId, name, 'l')];
|
||||
}
|
||||
|
||||
float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name,
|
||||
|
@ -497,10 +535,7 @@ namespace MWScript
|
|||
|
||||
const Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
|
||||
scriptId, name, 'f');
|
||||
|
||||
return locals.mFloats[index];
|
||||
return locals.mFloats[findLocalVariableIndex (scriptId, name, 'f')];
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberShort (const std::string& id, const std::string& name,
|
||||
|
@ -510,10 +545,7 @@ namespace MWScript
|
|||
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
|
||||
locals.mShorts[index] = value;
|
||||
locals.mShorts[findLocalVariableIndex (scriptId, name, 's')] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value, bool global)
|
||||
|
@ -522,10 +554,7 @@ namespace MWScript
|
|||
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
|
||||
locals.mLongs[index] = value;
|
||||
locals.mLongs[findLocalVariableIndex (scriptId, name, 'l')] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
|
||||
|
@ -534,14 +563,16 @@ namespace MWScript
|
|||
|
||||
Locals& locals = getMemberLocals (scriptId, global);
|
||||
|
||||
int index =
|
||||
MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
|
||||
locals.mFloats[index] = value;
|
||||
locals.mFloats[findLocalVariableIndex (scriptId, name, 'f')] = value;
|
||||
}
|
||||
|
||||
MWWorld::Ptr InterpreterContext::getReference(bool required)
|
||||
{
|
||||
return getReference ("", true, required);
|
||||
return getReferenceImp ("", true, required);
|
||||
}
|
||||
|
||||
std::string InterpreterContext::getTargetId() const
|
||||
{
|
||||
return mTargetId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,14 +27,22 @@ namespace MWScript
|
|||
class InterpreterContext : public Interpreter::Context
|
||||
{
|
||||
Locals *mLocals;
|
||||
MWWorld::Ptr mReference;
|
||||
mutable MWWorld::Ptr mReference;
|
||||
|
||||
MWWorld::Ptr mActivated;
|
||||
bool mActivationHandled;
|
||||
|
||||
MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true);
|
||||
std::string mTargetId;
|
||||
|
||||
const MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true) const;
|
||||
/// If \a id is empty, a reference the script is run from is returned or in case
|
||||
/// of a non-local script the reference derived from the target ID.
|
||||
MWWorld::Ptr getReferenceImp (const std::string& id = "", bool activeOnly = false,
|
||||
bool doThrow=true);
|
||||
|
||||
/// If \a id is empty, a reference the script is run from is returned or in case
|
||||
/// of a non-local script the reference derived from the target ID.
|
||||
const MWWorld::Ptr getReferenceImp (const std::string& id = "",
|
||||
bool activeOnly = false, bool doThrow=true) const;
|
||||
|
||||
const Locals& getMemberLocals (std::string& id, bool global) const;
|
||||
///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
|
||||
|
@ -42,9 +50,14 @@ namespace MWScript
|
|||
Locals& getMemberLocals (std::string& id, bool global);
|
||||
///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
|
||||
|
||||
/// Throws an exception if local variable can't be found.
|
||||
int findLocalVariableIndex (const std::string& scriptId, const std::string& name,
|
||||
char type) const;
|
||||
|
||||
public:
|
||||
|
||||
InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference);
|
||||
InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference,
|
||||
const std::string& targetId = "");
|
||||
///< The ownership of \a locals is not transferred. 0-pointer allowed.
|
||||
|
||||
virtual int getLocalShort (int index) const;
|
||||
|
@ -113,7 +126,7 @@ namespace MWScript
|
|||
|
||||
virtual bool isScriptRunning (const std::string& name) const;
|
||||
|
||||
virtual void startScript (const std::string& name);
|
||||
virtual void startScript (const std::string& name, const std::string& targetId = "");
|
||||
|
||||
virtual void stopScript (const std::string& name);
|
||||
|
||||
|
@ -158,6 +171,8 @@ namespace MWScript
|
|||
|
||||
MWWorld::Ptr getReference(bool required=true);
|
||||
///< Reference, that the script is running from (can be empty)
|
||||
|
||||
virtual std::string getTargetId() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,15 @@ namespace MWScript
|
|||
{
|
||||
void Locals::configure (const ESM::Script& script)
|
||||
{
|
||||
const Compiler::Locals& locals =
|
||||
MWBase::Environment::get().getScriptManager()->getLocals (script.mId);
|
||||
|
||||
mShorts.clear();
|
||||
mShorts.resize (script.mData.mNumShorts, 0);
|
||||
mShorts.resize (locals.get ('s').size(), 0);
|
||||
mLongs.clear();
|
||||
mLongs.resize (script.mData.mNumLongs, 0);
|
||||
mLongs.resize (locals.get ('l').size(), 0);
|
||||
mFloats.clear();
|
||||
mFloats.resize (script.mData.mNumFloats, 0);
|
||||
mFloats.resize (locals.get ('f').size(), 0);
|
||||
}
|
||||
|
||||
bool Locals::isEmpty() const
|
||||
|
@ -29,7 +32,7 @@ namespace MWScript
|
|||
|
||||
int Locals::getIntVar(const std::string &script, const std::string &var)
|
||||
{
|
||||
Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if(index != -1)
|
||||
|
@ -53,7 +56,7 @@ namespace MWScript
|
|||
|
||||
bool Locals::setVarByInt(const std::string& script, const std::string& var, int val)
|
||||
{
|
||||
Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
int index = locals.getIndex(var);
|
||||
char type = locals.getType(var);
|
||||
if(index != -1)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <algorithm>
|
||||
|
||||
#include <components/esm/loadscpt.hpp>
|
||||
|
||||
|
@ -22,12 +23,19 @@
|
|||
namespace MWScript
|
||||
{
|
||||
ScriptManager::ScriptManager (const MWWorld::ESMStore& store, bool verbose,
|
||||
Compiler::Context& compilerContext, int warningsMode)
|
||||
Compiler::Context& compilerContext, int warningsMode,
|
||||
const std::vector<std::string>& scriptBlacklist)
|
||||
: mErrorHandler (std::cerr), mStore (store), mVerbose (verbose),
|
||||
mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext),
|
||||
mOpcodesInstalled (false), mGlobalScripts (store)
|
||||
{
|
||||
mErrorHandler.setWarningsMode (warningsMode);
|
||||
|
||||
mScriptBlacklist.resize (scriptBlacklist.size());
|
||||
|
||||
std::transform (scriptBlacklist.begin(), scriptBlacklist.end(),
|
||||
mScriptBlacklist.begin(), Misc::StringUtils::lowerCase);
|
||||
std::sort (mScriptBlacklist.begin(), mScriptBlacklist.end());
|
||||
}
|
||||
|
||||
bool ScriptManager::compile (const std::string& name)
|
||||
|
@ -133,16 +141,22 @@ namespace MWScript
|
|||
int success = 0;
|
||||
|
||||
const MWWorld::Store<ESM::Script>& scripts = mStore.get<ESM::Script>();
|
||||
MWWorld::Store<ESM::Script>::iterator it = scripts.begin();
|
||||
|
||||
for (; it != scripts.end(); ++it, ++count)
|
||||
if (compile (it->mId))
|
||||
++success;
|
||||
for (MWWorld::Store<ESM::Script>::iterator iter = scripts.begin();
|
||||
iter != scripts.end(); ++iter)
|
||||
if (!std::binary_search (mScriptBlacklist.begin(), mScriptBlacklist.end(),
|
||||
Misc::StringUtils::lowerCase (iter->mId)))
|
||||
{
|
||||
++count;
|
||||
|
||||
if (compile (iter->mId))
|
||||
++success;
|
||||
}
|
||||
|
||||
return std::make_pair (count, success);
|
||||
}
|
||||
|
||||
Compiler::Locals& ScriptManager::getLocals (const std::string& name)
|
||||
const Compiler::Locals& ScriptManager::getLocals (const std::string& name)
|
||||
{
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
|
||||
|
@ -182,46 +196,4 @@ namespace MWScript
|
|||
{
|
||||
return mGlobalScripts;
|
||||
}
|
||||
|
||||
int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable,
|
||||
char type)
|
||||
{
|
||||
const ESM::Script *script = mStore.get<ESM::Script>().find (scriptId);
|
||||
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
|
||||
offset = 0;
|
||||
size = script->mData.mNumShorts;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
offset = script->mData.mNumShorts;
|
||||
size = script->mData.mNumLongs;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
offset = script->mData.mNumShorts+script->mData.mNumLongs;
|
||||
size = script->mData.mNumFloats;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
throw std::runtime_error ("invalid variable type");
|
||||
}
|
||||
|
||||
std::string variable2 = Misc::StringUtils::lowerCase (variable);
|
||||
|
||||
for (int i=0; i<size; ++i)
|
||||
if (Misc::StringUtils::lowerCase (script->mVarNames.at (i+offset))==variable2)
|
||||
return i;
|
||||
|
||||
throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,11 +48,13 @@ namespace MWScript
|
|||
ScriptCollection mScripts;
|
||||
GlobalScripts mGlobalScripts;
|
||||
std::map<std::string, Compiler::Locals> mOtherLocals;
|
||||
std::vector<std::string> mScriptBlacklist;
|
||||
|
||||
public:
|
||||
|
||||
ScriptManager (const MWWorld::ESMStore& store, bool verbose,
|
||||
Compiler::Context& compilerContext, int warningsMode);
|
||||
Compiler::Context& compilerContext, int warningsMode,
|
||||
const std::vector<std::string>& scriptBlacklist);
|
||||
|
||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext);
|
||||
///< Run the script with the given name (compile first, if not compiled yet)
|
||||
|
@ -65,15 +67,10 @@ namespace MWScript
|
|||
///< Compile all scripts
|
||||
/// \return count, success
|
||||
|
||||
virtual Compiler::Locals& getLocals (const std::string& name);
|
||||
virtual const Compiler::Locals& getLocals (const std::string& name);
|
||||
///< Return locals for script \a name.
|
||||
|
||||
virtual GlobalScripts& getGlobalScripts();
|
||||
|
||||
virtual int getLocalIndex (const std::string& scriptId, const std::string& variable,
|
||||
char type);
|
||||
///< Return index of the variable of the given name and type in the given script. Will
|
||||
/// throw an exception, if there is no such script or variable or the type does not match.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#ifdef OPENMW_USE_FFMPEG
|
||||
|
||||
|
||||
#include "ffmpeg_decoder.hpp"
|
||||
|
||||
// auto_ptr
|
||||
|
@ -375,5 +372,3 @@ FFmpeg_Decoder::~FFmpeg_Decoder()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,15 +17,10 @@
|
|||
|
||||
#include "openal_output.hpp"
|
||||
#define SOUND_OUT "OpenAL"
|
||||
/* Set up the sound manager to use FFMPEG for input.
|
||||
* The OPENMW_USE_x macros are set in CMakeLists.txt.
|
||||
*/
|
||||
#ifdef OPENMW_USE_FFMPEG
|
||||
#include "ffmpeg_decoder.hpp"
|
||||
#ifndef SOUND_IN
|
||||
#define SOUND_IN "FFmpeg"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace MWSound
|
||||
|
|
|
@ -132,12 +132,12 @@ void MWState::StateManager::newGame (bool bypass)
|
|||
{
|
||||
cleanup();
|
||||
|
||||
MWBase::Environment::get().getWorld()->startNewGame (bypass);
|
||||
|
||||
if (!bypass)
|
||||
MWBase::Environment::get().getWindowManager()->setNewGame (true);
|
||||
else
|
||||
MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1);
|
||||
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
|
||||
|
||||
MWBase::Environment::get().getWorld()->startNewGame (bypass);
|
||||
|
||||
mState = State_Running;
|
||||
}
|
||||
|
@ -401,6 +401,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
|||
// Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again
|
||||
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false);
|
||||
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
|
||||
|
||||
// Do not trigger erroneous cellChanged events
|
||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||
}
|
||||
|
|
|
@ -211,9 +211,9 @@ namespace MWWorld
|
|||
// set new game mark
|
||||
mGlobalVariables["chargenstate"].setInteger (1);
|
||||
mGlobalVariables["pcrace"].setInteger (3);
|
||||
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
|
||||
}
|
||||
else
|
||||
mGlobalVariables["chargenstate"].setInteger (-1);
|
||||
|
||||
if (bypass && !mStartCell.empty())
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ add_component_dir (compiler
|
|||
context controlparser errorhandler exception exprparser extensions fileparser generator
|
||||
lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler
|
||||
stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser
|
||||
quickfileparser
|
||||
quickfileparser discardparser
|
||||
)
|
||||
|
||||
add_component_dir (interpreter
|
||||
|
|
70
components/compiler/discardparser.cpp
Normal file
70
components/compiler/discardparser.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
#include "discardparser.hpp"
|
||||
|
||||
#include "scanner.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
DiscardParser::DiscardParser (ErrorHandler& errorHandler, const Context& context)
|
||||
: Parser (errorHandler, context), mState (StartState)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DiscardParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==StartState || mState==CommaState || mState==MinusState)
|
||||
{
|
||||
start();
|
||||
return false;
|
||||
}
|
||||
|
||||
return Parser::parseInt (value, loc, scanner);
|
||||
}
|
||||
|
||||
bool DiscardParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==StartState || mState==CommaState || mState==MinusState)
|
||||
{
|
||||
start();
|
||||
return false;
|
||||
}
|
||||
|
||||
return Parser::parseFloat (value, loc, scanner);
|
||||
}
|
||||
|
||||
bool DiscardParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner)
|
||||
{
|
||||
if (mState==StartState || mState==CommaState)
|
||||
{
|
||||
start();
|
||||
return false;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
bool DiscardParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (code==Scanner::S_comma && mState==StartState)
|
||||
{
|
||||
mState = CommaState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_minus && (mState==StartState || mState==CommaState))
|
||||
{
|
||||
mState = MinusState;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseSpecial (code, loc, scanner);
|
||||
}
|
||||
|
||||
void DiscardParser::reset()
|
||||
{
|
||||
mState = StartState;
|
||||
Parser::reset();
|
||||
}
|
||||
}
|
45
components/compiler/discardparser.hpp
Normal file
45
components/compiler/discardparser.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef COMPILER_DISCARDPARSER_H_INCLUDED
|
||||
#define COMPILER_DISCARDPARSER_H_INCLUDED
|
||||
|
||||
#include "parser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
/// \brief Parse a single optional numeric value or string and discard it
|
||||
class DiscardParser : public Parser
|
||||
{
|
||||
enum State
|
||||
{
|
||||
StartState, CommaState, MinusState
|
||||
};
|
||||
|
||||
State mState;
|
||||
|
||||
public:
|
||||
|
||||
DiscardParser (ErrorHandler& errorHandler, const Context& context);
|
||||
|
||||
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle an int token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a float token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner);
|
||||
///< Handle a name token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a special character token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual void reset();
|
||||
///< Reset parser to clean state.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,11 +3,8 @@
|
|||
|
||||
namespace Compiler
|
||||
{
|
||||
// constructor
|
||||
|
||||
ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0), mWarningsMode (1) {}
|
||||
|
||||
// destructor
|
||||
ErrorHandler::ErrorHandler()
|
||||
: mWarnings (0), mErrors (0), mWarningsMode (1), mDowngradeErrors (false) {}
|
||||
|
||||
ErrorHandler::~ErrorHandler() {}
|
||||
|
||||
|
@ -49,6 +46,12 @@ namespace Compiler
|
|||
|
||||
void ErrorHandler::error (const std::string& message, const TokenLoc& loc)
|
||||
{
|
||||
if (mDowngradeErrors)
|
||||
{
|
||||
warning (message, loc);
|
||||
return;
|
||||
}
|
||||
|
||||
++mErrors;
|
||||
report (message, loc, ErrorMessage);
|
||||
}
|
||||
|
@ -72,4 +75,21 @@ namespace Compiler
|
|||
{
|
||||
mWarningsMode = mode;
|
||||
}
|
||||
|
||||
void ErrorHandler::downgradeErrors (bool downgrade)
|
||||
{
|
||||
mDowngradeErrors = downgrade;
|
||||
}
|
||||
|
||||
|
||||
ErrorDowngrade::ErrorDowngrade (ErrorHandler& handler) : mHandler (handler)
|
||||
{
|
||||
mHandler.downgradeErrors (true);
|
||||
}
|
||||
|
||||
ErrorDowngrade::~ErrorDowngrade()
|
||||
{
|
||||
mHandler.downgradeErrors (false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Compiler
|
|||
int mWarnings;
|
||||
int mErrors;
|
||||
int mWarningsMode;
|
||||
bool mDowngradeErrors;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -66,6 +67,26 @@ namespace Compiler
|
|||
|
||||
void setWarningsMode (int mode);
|
||||
///< // 0 ignore, 1 rate as warning, 2 rate as error
|
||||
|
||||
/// Treat errors as warnings.
|
||||
void downgradeErrors (bool downgrade);
|
||||
};
|
||||
|
||||
class ErrorDowngrade
|
||||
{
|
||||
ErrorHandler& mHandler;
|
||||
|
||||
/// not implemented
|
||||
ErrorDowngrade (const ErrorDowngrade&);
|
||||
|
||||
/// not implemented
|
||||
ErrorDowngrade& operator= (const ErrorDowngrade&);
|
||||
|
||||
public:
|
||||
|
||||
ErrorDowngrade (ErrorHandler& handler);
|
||||
|
||||
~ErrorDowngrade();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "stringparser.hpp"
|
||||
#include "extensions.hpp"
|
||||
#include "context.hpp"
|
||||
#include "discardparser.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -386,6 +387,9 @@ namespace Compiler
|
|||
mExplicit.clear();
|
||||
mRefOp = false;
|
||||
|
||||
std::vector<Interpreter::Type_Code> ignore;
|
||||
parseArguments ("x", scanner, ignore);
|
||||
|
||||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -404,6 +408,21 @@ namespace Compiler
|
|||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
else if (keyword==Scanner::K_scriptrunning)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("c", scanner);
|
||||
|
||||
Generator::scriptRunning (mCode);
|
||||
mOperands.push_back ('l');
|
||||
|
||||
mExplicit.clear();
|
||||
mRefOp = false;
|
||||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for custom extensions
|
||||
if (const Extensions *extensions = getContext().getExtensions())
|
||||
|
@ -527,6 +546,9 @@ namespace Compiler
|
|||
Generator::getDisabled (mCode, mLiterals, "");
|
||||
mOperands.push_back ('l');
|
||||
|
||||
std::vector<Interpreter::Type_Code> ignore;
|
||||
parseArguments ("x", scanner, ignore);
|
||||
|
||||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -737,6 +759,7 @@ namespace Compiler
|
|||
|
||||
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
||||
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
||||
DiscardParser discardParser (getErrorHandler(), getContext());
|
||||
|
||||
std::stack<std::vector<Interpreter::Type_Code> > stack;
|
||||
|
||||
|
@ -771,11 +794,32 @@ namespace Compiler
|
|||
++optionalCount;
|
||||
}
|
||||
}
|
||||
else if (*iter=='X')
|
||||
{
|
||||
parser.reset();
|
||||
|
||||
parser.setOptional (true);
|
||||
|
||||
scanner.scan (parser);
|
||||
|
||||
if (parser.isEmpty())
|
||||
break;
|
||||
}
|
||||
else if (*iter=='z')
|
||||
{
|
||||
discardParser.reset();
|
||||
discardParser.setOptional (true);
|
||||
|
||||
scanner.scan (discardParser);
|
||||
|
||||
if (discardParser.isEmpty())
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.reset();
|
||||
|
||||
if (optional || *iter == 'X')
|
||||
if (optional)
|
||||
parser.setOptional (true);
|
||||
|
||||
scanner.scan (parser);
|
||||
|
@ -783,20 +827,17 @@ namespace Compiler
|
|||
if (optional && parser.isEmpty())
|
||||
break;
|
||||
|
||||
if (*iter != 'X')
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
|
||||
char type = parser.append (tmp);
|
||||
char type = parser.append (tmp);
|
||||
|
||||
if (type!=*iter)
|
||||
Generator::convert (tmp, type, *iter);
|
||||
if (type!=*iter)
|
||||
Generator::convert (tmp, type, *iter);
|
||||
|
||||
stack.push (tmp);
|
||||
stack.push (tmp);
|
||||
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace Compiler
|
|||
s - Short <BR>
|
||||
S - String, case preserved <BR>
|
||||
x - Optional, ignored string argument
|
||||
X - Optional, ignored integer argument
|
||||
X - Optional, ignored numeric expression
|
||||
z - Optional, ignored string or numeric argument
|
||||
**/
|
||||
typedef std::string ScriptArgs;
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace Compiler
|
|||
opcodeGetItemCountExplicit);
|
||||
extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem,
|
||||
opcodeRemoveItemExplicit);
|
||||
extensions.registerInstruction ("equip", "c", opcodeEquip, opcodeEquipExplicit);
|
||||
extensions.registerInstruction ("equip", "cX", opcodeEquip, opcodeEquipExplicit);
|
||||
extensions.registerFunction ("getarmortype", 'l', "l", opcodeGetArmorType, opcodeGetArmorTypeExplicit);
|
||||
extensions.registerFunction ("hasitemequipped", 'l', "c", opcodeHasItemEquipped, opcodeHasItemEquippedExplicit);
|
||||
extensions.registerFunction ("hassoulgem", 'l', "c", opcodeHasSoulGem, opcodeHasSoulGemExplicit);
|
||||
|
@ -410,7 +410,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel);
|
||||
extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel);
|
||||
|
||||
extensions.registerInstruction ("addspell", "cxX", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("addspell", "cz", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||
opcodeRemoveSpellExplicit);
|
||||
extensions.registerInstruction ("removespelleffects", "c", opcodeRemoveSpellEffects,
|
||||
|
|
|
@ -51,6 +51,12 @@ namespace Compiler
|
|||
/// \todo allow this workaround to be disabled for newer scripts
|
||||
}
|
||||
|
||||
if (mState==BeginCompleteState)
|
||||
{
|
||||
reportWarning ("Stray string (" + name + ") after begin statement", loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
|
|
|
@ -300,9 +300,9 @@ namespace
|
|||
code.push_back (Compiler::Generator::segment5 (46));
|
||||
}
|
||||
|
||||
void opStartScript (Compiler::Generator::CodeContainer& code)
|
||||
void opStartScript (Compiler::Generator::CodeContainer& code, bool targeted)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (47));
|
||||
code.push_back (Compiler::Generator::segment5 (targeted ? 71 : 47));
|
||||
}
|
||||
|
||||
void opStopScript (Compiler::Generator::CodeContainer& code)
|
||||
|
@ -830,9 +830,16 @@ namespace Compiler
|
|||
opScriptRunning (code);
|
||||
}
|
||||
|
||||
void startScript (CodeContainer& code)
|
||||
void startScript (CodeContainer& code, Literals& literals, const std::string& id)
|
||||
{
|
||||
opStartScript (code);
|
||||
if (id.empty())
|
||||
opStartScript (code, false);
|
||||
else
|
||||
{
|
||||
int index = literals.addString (id);
|
||||
opPushInt (code, index);
|
||||
opStartScript (code, true);
|
||||
}
|
||||
}
|
||||
|
||||
void stopScript (CodeContainer& code)
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace Compiler
|
|||
|
||||
void scriptRunning (CodeContainer& code);
|
||||
|
||||
void startScript (CodeContainer& code);
|
||||
void startScript (CodeContainer& code, Literals& literals, const std::string& id);
|
||||
|
||||
void stopScript (CodeContainer& code);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "generator.hpp"
|
||||
#include "extensions.hpp"
|
||||
#include "declarationparser.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -262,6 +263,20 @@ namespace Compiler
|
|||
Generator::disable (mCode, mLiterals, mExplicit);
|
||||
mState = PotentialEndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_startscript:
|
||||
|
||||
mExprParser.parseArguments ("c", scanner, mCode);
|
||||
Generator::startScript (mCode, mLiterals, mExplicit);
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_stopscript:
|
||||
|
||||
mExprParser.parseArguments ("c", scanner, mCode);
|
||||
Generator::stopScript (mCode);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for custom extensions
|
||||
|
@ -278,9 +293,31 @@ namespace Compiler
|
|||
mExplicit.clear();
|
||||
}
|
||||
|
||||
int optionals = mExprParser.parseArguments (argumentType, scanner, mCode);
|
||||
int optionals = 0;
|
||||
|
||||
try
|
||||
{
|
||||
ErrorDowngrade errorDowngrade (getErrorHandler());
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
optionals = mExprParser.parseArguments (argumentType, scanner, code);
|
||||
mCode.insert (mCode.begin(), code.begin(), code.end());
|
||||
extensions->generateInstructionCode (keyword, mCode, mLiterals,
|
||||
mExplicit, optionals);
|
||||
}
|
||||
catch (const SourceException& exception)
|
||||
{
|
||||
// Ignore argument exceptions for positioncell.
|
||||
/// \todo add option to disable this
|
||||
if (Misc::StringUtils::lowerCase (loc.mLiteral)=="positioncell")
|
||||
{
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
@ -349,7 +386,7 @@ namespace Compiler
|
|||
if (declaration.parseKeyword (keyword, loc, scanner))
|
||||
scanner.scan (declaration);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case Scanner::K_set: mState = SetState; return true;
|
||||
|
@ -361,13 +398,6 @@ namespace Compiler
|
|||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_startscript:
|
||||
|
||||
mExprParser.parseArguments ("c", scanner, mCode);
|
||||
Generator::startScript (mCode);
|
||||
mState = EndState;
|
||||
return true;
|
||||
|
||||
case Scanner::K_stopscript:
|
||||
|
||||
mExprParser.parseArguments ("c", scanner, mCode);
|
||||
|
|
|
@ -17,8 +17,6 @@ namespace Compiler
|
|||
|
||||
int searchIndex (char type, const std::string& name) const;
|
||||
|
||||
bool search (char type, const std::string& name) const;
|
||||
|
||||
std::vector<std::string>& get (char type);
|
||||
|
||||
public:
|
||||
|
@ -29,6 +27,10 @@ namespace Compiler
|
|||
int getIndex (const std::string& name) const;
|
||||
///< return index for local variable \a name (-1: does not exist).
|
||||
|
||||
/// Return index for local variable \a name of type \a type (-1: variable does not
|
||||
/// exit).
|
||||
bool search (char type, const std::string& name) const;
|
||||
|
||||
const std::vector<std::string>& get (char type) const;
|
||||
|
||||
void write (std::ostream& localFile) const;
|
||||
|
|
|
@ -343,17 +343,13 @@ namespace Compiler
|
|||
}
|
||||
else if (!(c=='"' && name.empty()))
|
||||
{
|
||||
if (!(std::isalpha (c) || std::isdigit (c) || c=='_' || c=='`' ||
|
||||
/// \todo add an option to disable the following hack. Also, find out who is
|
||||
/// responsible for allowing it in the first place and meet up with that person in
|
||||
/// a dark alley.
|
||||
(c=='-' && !name.empty() && std::isalpha (mStream.peek()))))
|
||||
if (!isStringCharacter (c))
|
||||
{
|
||||
putback (c);
|
||||
break;
|
||||
}
|
||||
|
||||
if (first && std::isdigit (c))
|
||||
if (first && (std::isdigit (c) || c=='`' || c=='-'))
|
||||
error = true;
|
||||
}
|
||||
|
||||
|
@ -499,6 +495,17 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Scanner::isStringCharacter (char c, bool lookAhead)
|
||||
{
|
||||
return std::isalpha (c) || std::isdigit (c) || c=='_' ||
|
||||
/// \todo disable this when doing more stricter compiling
|
||||
c=='`' ||
|
||||
/// \todo disable this when doing more stricter compiling. Also, find out who is
|
||||
/// responsible for allowing it in the first place and meet up with that person in
|
||||
/// a dark alley.
|
||||
(c=='-' && (!lookAhead || isStringCharacter (mStream.peek(), false)));
|
||||
}
|
||||
|
||||
bool Scanner::isWhitespace (char c)
|
||||
{
|
||||
return c==' ' || c=='\t';
|
||||
|
|
|
@ -92,6 +92,8 @@ namespace Compiler
|
|||
|
||||
bool scanSpecial (char c, Parser& parser, bool& cont);
|
||||
|
||||
bool isStringCharacter (char c, bool lookAhead = true);
|
||||
|
||||
static bool isWhitespace (char c);
|
||||
|
||||
public:
|
||||
|
|
|
@ -12,6 +12,8 @@ void ESM::GlobalScript::load (ESMReader &esm)
|
|||
|
||||
mRunning = 0;
|
||||
esm.getHNOT (mRunning, "RUN_");
|
||||
|
||||
mTargetId = esm.getHNOString ("TARG");
|
||||
}
|
||||
|
||||
void ESM::GlobalScript::save (ESMWriter &esm) const
|
||||
|
@ -22,4 +24,6 @@ void ESM::GlobalScript::save (ESMWriter &esm) const
|
|||
|
||||
if (mRunning)
|
||||
esm.writeHNT ("RUN_", mRunning);
|
||||
|
||||
esm.writeHNOString ("TARG", mTargetId);
|
||||
}
|
|
@ -15,6 +15,7 @@ namespace ESM
|
|||
std::string mId;
|
||||
Locals mLocals;
|
||||
int mRunning;
|
||||
std::string mTargetId; // for targeted scripts
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
|
|
|
@ -23,29 +23,8 @@ public:
|
|||
|
||||
struct SCHDstruct
|
||||
{
|
||||
/* Script name.
|
||||
|
||||
NOTE: You should handle the name "Main" (case insensitive) with
|
||||
care. With tribunal, modders got the ability to add 'start
|
||||
scripts' to their mods, which is a script that is run at
|
||||
startup and which runs throughout the game (I think.)
|
||||
|
||||
However, before Tribunal, there was only one startup script,
|
||||
called "Main". If mods wanted to make their own start scripts,
|
||||
they had to overwrite Main. This is obviously problem if
|
||||
multiple mods to this at the same time.
|
||||
|
||||
Although most mods have switched to using Trib-style startup
|
||||
scripts, some legacy mods might still overwrite Main, and this
|
||||
can cause problems if several mods do it. I think the best
|
||||
course of action is to NEVER overwrite main, but instead add
|
||||
each with a separate unique name and add them to the start
|
||||
script list. But there might be other problems with this
|
||||
approach though.
|
||||
*/
|
||||
|
||||
// These describe the sizes we need to allocate for the script
|
||||
// data.
|
||||
/// Data from script-precompling in the editor.
|
||||
/// \warning Do not use them. OpenCS currently does not precompile scripts.
|
||||
int mNumShorts, mNumLongs, mNumFloats, mScriptDataSize, mStringTableSize;
|
||||
}; // 52 bytes
|
||||
|
||||
|
@ -53,9 +32,16 @@ public:
|
|||
|
||||
SCHDstruct mData;
|
||||
|
||||
std::vector<std::string> mVarNames; // Variable names
|
||||
std::vector<unsigned char> mScriptData; // Compiled bytecode
|
||||
std::string mScriptText; // Uncompiled script
|
||||
/// Variable names generated by script-precompiling in the editor.
|
||||
/// \warning Do not use this field. OpenCS currently does not precompile scripts.
|
||||
std::vector<std::string> mVarNames;
|
||||
|
||||
/// Bytecode generated from script-precompiling in the editor.
|
||||
/// \warning Do not use this field. OpenCS currently does not precompile scripts.
|
||||
std::vector<unsigned char> mScriptData;
|
||||
|
||||
/// Script source code
|
||||
std::string mScriptText;
|
||||
|
||||
void load(ESMReader &esm);
|
||||
void save(ESMWriter &esm) const;
|
||||
|
|
|
@ -16,13 +16,19 @@ namespace Files
|
|||
|
||||
static const char* const openmwCfgFile = "openmw.cfg";
|
||||
|
||||
#if defined(_WIN32) || defined(__WINDOWS__)
|
||||
static const char* const applicationName = "OpenMW";
|
||||
#else
|
||||
static const char* const applicationName = "openmw";
|
||||
#endif
|
||||
|
||||
const char* const mwToken = "?mw?";
|
||||
const char* const localToken = "?local?";
|
||||
const char* const userDataToken = "?userdata?";
|
||||
const char* const globalToken = "?global?";
|
||||
|
||||
ConfigurationManager::ConfigurationManager()
|
||||
: mFixedPath("openmw")
|
||||
: mFixedPath(applicationName)
|
||||
{
|
||||
setupTokensMapping();
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Interpreter
|
|||
|
||||
virtual bool isScriptRunning (const std::string& name) const = 0;
|
||||
|
||||
virtual void startScript (const std::string& name) = 0;
|
||||
virtual void startScript (const std::string& name, const std::string& targetId = "") = 0;
|
||||
|
||||
virtual void stopScript (const std::string& name) = 0;
|
||||
|
||||
|
@ -108,6 +108,8 @@ namespace Interpreter
|
|||
|
||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
|
||||
= 0;
|
||||
|
||||
virtual std::string getTargetId() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -133,5 +133,6 @@ op 67: store stack[0] in member float stack[2] of global script with ID stack[1]
|
|||
op 68: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||
op 69: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||
op 70: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||
opcodes 71-33554431 unused
|
||||
op 71: explicit reference (target) = stack[0]; pop; start script stack[0] and pop
|
||||
opcodes 72-33554431 unused
|
||||
opcodes 33554432-67108863 reserved for extensions
|
||||
|
|
|
@ -113,6 +113,7 @@ namespace Interpreter
|
|||
interpreter.installSegment5 (46, new OpScriptRunning);
|
||||
interpreter.installSegment5 (47, new OpStartScript);
|
||||
interpreter.installSegment5 (48, new OpStopScript);
|
||||
interpreter.installSegment5 (71, new OpStartScriptExplicit);
|
||||
|
||||
// spacial
|
||||
interpreter.installSegment5 (49, new OpGetDistance);
|
||||
|
|
|
@ -10,36 +10,52 @@ namespace Interpreter
|
|||
class OpScriptRunning : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime[0].mInteger = runtime.getContext().isScriptRunning (name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class OpStartScript : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
runtime.getContext().startScript (name);
|
||||
}
|
||||
runtime.getContext().startScript (name, runtime.getContext().getTargetId());
|
||||
}
|
||||
};
|
||||
|
||||
class OpStartScriptExplicit : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
std::string targetId = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
runtime.getContext().startScript (name, targetId);
|
||||
}
|
||||
};
|
||||
|
||||
class OpStopScript : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
runtime.getContext().stopScript (name);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ Sandy Carter (bwrsandman)
|
|||
Sebastian Wick (swick)
|
||||
Sergey Shambir
|
||||
sir_herrbatka
|
||||
Stefan Galowicz (bogglez)
|
||||
Sylvain Thesnieres (Garvek)
|
||||
Thomas Luppi (Digmaster)
|
||||
Tom Mason (wheybags)
|
||||
|
|
|
@ -2,3 +2,6 @@ data="?global?data"
|
|||
data="?mw?Data Files"
|
||||
data-local="?userdata?data"
|
||||
resources=${OPENMW_RESOURCE_FILES}
|
||||
script-blacklist=Museum
|
||||
script-blacklist=MockChangeScript
|
||||
script-blacklist=doortestwarp
|
||||
|
|
|
@ -3,3 +3,6 @@ data="?mw?Data Files"
|
|||
data=./data
|
||||
data-local="?userdata?data"
|
||||
resources=./resources
|
||||
script-blacklist=Museum
|
||||
script-blacklist=MockChangeScript
|
||||
script-blacklist=doortestwarp
|
||||
|
|
|
@ -130,6 +130,7 @@ Bug #1179: Crash after trying to load game after being killed
|
|||
Bug #1180: Changing footstep sound location
|
||||
Bug #1196: Jumping not disabled when showing messageboxes
|
||||
Bug #1202: "strange" keys are not shown in binding menu, and are not saved either, but works
|
||||
Bug #1216: Broken dialog topics in russian Morrowind
|
||||
Bug #1217: Container content changes based on the current position of the mouse
|
||||
Bug #1234: Loading/saving issues with dynamic records
|
||||
Bug #1277: Text pasted into the console appears twice
|
||||
|
@ -248,6 +249,8 @@ Bug #1590: Failed to save game: compile error
|
|||
Bug #1598: Segfault when making Drain/Fortify Skill spells
|
||||
Bug #1599: Unable to switch to fullscreen
|
||||
Bug #1613: Morrowind Rebirth duplicate objects / vanilla objects not removed
|
||||
Bug #1618: Death notice fails to show up
|
||||
Bug #1628: Alt+Tab Segfault
|
||||
Feature #32: Periodic Cleanup/Refill
|
||||
Feature #41: Precipitation and weather particles
|
||||
Feature #568: Editor: Configuration setup
|
||||
|
|
Loading…
Reference in a new issue