diff --git a/CMakeLists.txt b/CMakeLists.txt
index 338a5e7e7..e8152f2f9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@ include (OpenMWMacros)
# Version
set (OPENMW_VERSION_MAJOR 0)
-set (OPENMW_VERSION_MINOR 12)
+set (OPENMW_VERSION_MINOR 13)
set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@@ -185,6 +185,11 @@ endif (APPLE)
# Dependencies
+# Fix for not visible pthreads functions for linker with glibc 2.15
+if (UNIX AND NOT APPLE)
+find_package (Threads)
+endif()
+
find_package(OGRE REQUIRED)
find_package(MyGUI REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
@@ -315,7 +320,7 @@ if(DPKG_PROGRAM)
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher")
- SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libogre-1.7.3 (>= 1.7.3), libbullet0 (>= 2.77), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
+ SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
@@ -451,7 +456,9 @@ if (WIN32)
endforeach(d)
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
- set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
+ if (BUILD_LAUNCHER)
+ set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
+ endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif(MSVC)
diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp
index 054cbf141..c96fc2c7b 100644
--- a/apps/launcher/datafilespage.cpp
+++ b/apps/launcher/datafilespage.cpp
@@ -222,7 +222,7 @@ void DataFilesPage::setupDataFiles()
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
- msgBox.setIcon(QMessageBox::Critical);
+ msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("
Could not find the Data Files location
\
The directory containing the Data Files was not found.
\
@@ -279,72 +279,79 @@ void DataFilesPage::setupDataFiles()
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) {
- ESMReader fileReader;
- QStringList availableMasters; // Will contain all found masters
- fileReader.setEncoding(variables["encoding"].as());
- fileReader.open(iter->second.string());
+ try {
+ ESMReader fileReader;
+ QStringList availableMasters; // Will contain all found masters
+
+ fileReader.setEncoding(variables["encoding"].as());
+ fileReader.open(iter->second.string());
- // First we fill the availableMasters and the mMastersWidget
- ESMReader::MasterList mlist = fileReader.getMasters();
+ // First we fill the availableMasters and the mMastersWidget
+ ESMReader::MasterList mlist = fileReader.getMasters();
- for (unsigned int i = 0; i < mlist.size(); ++i) {
- const QString currentMaster = QString::fromStdString(mlist[i].name);
- availableMasters.append(currentMaster);
+ for (unsigned int i = 0; i < mlist.size(); ++i) {
+ const QString currentMaster = QString::fromStdString(mlist[i].name);
+ availableMasters.append(currentMaster);
- const QList itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
+ const QList itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
- if (itemList.isEmpty()) { // Master is not yet in the widget
- mMastersWidget->insertRow(i);
+ if (itemList.isEmpty()) { // Master is not yet in the widget
+ mMastersWidget->insertRow(i);
- QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
- item->setForeground(Qt::red);
- item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
+ QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
+ item->setForeground(Qt::red);
+ item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
- mMastersWidget->setItem(i, 0, item);
+ mMastersWidget->setItem(i, 0, item);
+ }
}
- }
- availableMasters.sort(); // Sort the masters alphabetically
+ availableMasters.sort(); // Sort the masters alphabetically
- // Now we put the current plugin in the mDataFilesModel under its masters
- QStandardItem *parent = new QStandardItem(availableMasters.join(","));
+ // Now we put the current plugin in the mDataFilesModel under its masters
+ QStandardItem *parent = new QStandardItem(availableMasters.join(","));
- QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
- QStandardItem *child = new QStandardItem(fileName);
+ QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
+ QStandardItem *child = new QStandardItem(fileName);
- // Tooltip information
- QString author = QString::fromStdString(fileReader.getAuthor());
- float version = fileReader.getFVer();
- QString description = QString::fromStdString(fileReader.getDesc());
+ // Tooltip information
+ QString author = QString::fromStdString(fileReader.getAuthor());
+ float version = fileReader.getFVer();
+ QString description = QString::fromStdString(fileReader.getDesc());
- // For the date created/modified
- QFileInfo fi(QString::fromStdString(iter->second.string()));
+ // For the date created/modified
+ QFileInfo fi(QString::fromStdString(iter->second.string()));
- QString toolTip= QString("Author: %1
\
- Version: %2
\
- Description:
\
- %3
\
- Created on: %4
\
- Last modified: %5")
- .arg(author)
- .arg(version)
- .arg(description)
- .arg(fi.created().toString(Qt::TextDate))
- .arg(fi.lastModified().toString(Qt::TextDate));
+ QString toolTip= QString("Author: %1
\
+ Version: %2
\
+ Description:
\
+ %3
\
+ Created on: %4
\
+ Last modified: %5")
+ .arg(author)
+ .arg(version)
+ .arg(description)
+ .arg(fi.created().toString(Qt::TextDate))
+ .arg(fi.lastModified().toString(Qt::TextDate));
- child->setToolTip(toolTip);
+ child->setToolTip(toolTip);
- const QList masterList = mDataFilesModel->findItems(availableMasters.join(","));
+ const QList masterList = mDataFilesModel->findItems(availableMasters.join(","));
- if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
- parent->appendRow(child);
- mDataFilesModel->appendRow(parent);
- } else {
- // Masters node exists, append current plugin
- foreach (QStandardItem *currentItem, masterList) {
- currentItem->appendRow(child);
+ if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
+ parent->appendRow(child);
+ mDataFilesModel->appendRow(parent);
+ } else {
+ // Masters node exists, append current plugin
+ foreach (QStandardItem *currentItem, masterList) {
+ currentItem->appendRow(child);
+ }
}
+
+ } catch(std::runtime_error &e) {
+ // An error occurred while reading the .esp
+ continue;
}
}
diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt
index d6101c919..929b579b8 100644
--- a/apps/openmw/CMakeLists.txt
+++ b/apps/openmw/CMakeLists.txt
@@ -81,7 +81,7 @@ add_definitions(${SOUND_DEFINE})
target_link_libraries(openmw
${OGRE_LIBRARIES}
- ${OGRE_STATIC_PLUGINS}
+ ${OGRE_STATIC_PLUGINS}
${OIS_LIBRARIES}
${Boost_LIBRARIES}
${OPENAL_LIBRARY}
@@ -92,6 +92,11 @@ target_link_libraries(openmw
components
)
+# Fix for not visible pthreads functions for linker with glibc 2.15
+if (UNIX AND NOT APPLE)
+target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
+endif()
+
if(APPLE)
find_library(CARBON_FRAMEWORK Carbon)
target_link_libraries(openmw ${CARBON_FRAMEWORK})
diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp
index fcdd0bf99..89068ce53 100644
--- a/apps/openmw/engine.cpp
+++ b/apps/openmw/engine.cpp
@@ -60,7 +60,7 @@ void OMW::Engine::executeLocalScripts()
MWScript::InterpreterContext interpreterContext (mEnvironment,
&script.second.getRefData().getLocals(), script.second);
- mScriptManager->run (script.first, interpreterContext);
+ mEnvironment.mScriptManager->run (script.first, interpreterContext);
if (mEnvironment.mWorld->hasCellChanged())
break;
@@ -182,7 +182,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mCompileAll (false)
, mReportFocus (false)
, mFocusTDiff (0)
- , mScriptManager (0)
, mScriptContext (0)
, mFSStrict (false)
, mCfgMgr(configurationManager)
@@ -199,7 +198,7 @@ OMW::Engine::~Engine()
delete mEnvironment.mMechanicsManager;
delete mEnvironment.mDialogueManager;
delete mEnvironment.mJournal;
- delete mScriptManager;
+ delete mEnvironment.mScriptManager;
delete mScriptContext;
delete mOgre;
}
@@ -348,18 +347,18 @@ void OMW::Engine::go()
mEnvironment);
mScriptContext->setExtensions (&mExtensions);
- mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts,
- *mScriptContext);
+ mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(),
+ mVerboseScripts, *mScriptContext);
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
- *mScriptManager);
+ *mEnvironment.mScriptManager);
// Create game mechanics system
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
// Create dialog system
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
- mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment);
+ mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment,mExtensions);
// load cell
ESM::Position pos;
@@ -393,7 +392,7 @@ void OMW::Engine::go()
// scripts
if (mCompileAll)
{
- std::pair result = mScriptManager->compileAll();
+ std::pair result = mEnvironment.mScriptManager->compileAll();
if (result.first)
std::cout
@@ -438,7 +437,7 @@ void OMW::Engine::activate()
if (!script.empty())
{
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
- mScriptManager->run (script, interpreterContext);
+ mEnvironment.mScriptManager->run (script, interpreterContext);
}
if (!interpreterContext.hasActivationBeenHandled())
diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp
index 5c5cdc018..690430784 100644
--- a/apps/openmw/engine.hpp
+++ b/apps/openmw/engine.hpp
@@ -78,10 +78,9 @@ namespace OMW
std::string mFocusName;
MWWorld::Environment mEnvironment;
- MWScript::ScriptManager *mScriptManager;
Compiler::Extensions mExtensions;
Compiler::Context *mScriptContext;
-
+
Files::Collections mFileCollections;
bool mFSStrict;
diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp
index f78160cd7..50549f4a5 100644
--- a/apps/openmw/mwdialogue/dialoguemanager.cpp
+++ b/apps/openmw/mwdialogue/dialoguemanager.cpp
@@ -9,16 +9,36 @@
#include
+
#include "../mwworld/class.hpp"
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/refdata.hpp"
#include "../mwworld/player.hpp"
+#include "../mwworld/containerstore.hpp"
#include "../mwinput/inputmanager.hpp"
+#include "../mwgui/dialogue.hpp"
+#include "../mwgui/window_manager.hpp"
+
+#include "journal.hpp"
#include
+#include "../mwscript/extensions.hpp"
+#include "../mwscript/scriptmanager.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../mwscript/compilercontext.hpp"
+#include "../mwscript/interpretercontext.hpp"
+#include
+
namespace
{
std::string toLower (const std::string& name)
@@ -31,17 +51,18 @@ namespace
return lowerCase;
}
+
template
bool selectCompare (char comp, T1 value1, T2 value2)
{
switch (comp)
{
- case '0': return value1==value2;
- case '1': return value1!=value2;
- case '2': return value1>value2;
- case '3': return value1>=value2;
- case '4': return value1value2;
+ case '3': return value1>=value2;
+ case '4': return value1::const_iterator iter (info.selects.begin());
+ iter != info.selects.end(); ++iter)
+ {
+ ESM::DialInfo::SelectStruct select = *iter;
+ char type = select.selectRule[1];
+ if(type == '1')
+ {
+ char comp = select.selectRule[4];
+ std::string name = select.selectRule.substr (5);
+ std::string function = select.selectRule.substr(2,2);
+
+ int ifunction;
+ std::istringstream iss(function);
+ iss >> ifunction;
+ switch(ifunction)
+ {
+ case 39://PC Expelled
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 40://PC Common Disease
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 41://PC Blight Disease
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 43://PC Crime level
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 46://Same faction
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 48://Detected
+ if(!selectCompare(comp,1,select.i)) return false;
+ break;
+
+ case 49://Alarmed
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 50://choice
+
+ if(choice)
+ {
+ if(!selectCompare(comp,mChoice,select.i)) return false;
+ }
+ break;
+
+ case 60://PC Vampire
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 61://Level
+ if(!selectCompare(comp,1,select.i)) return false;
+ break;
+
+ case 62://Attacked
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 63://Talked to PC
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 64://PC Health
+ if(!selectCompare(comp,50,select.i)) return false;
+ break;
+
+ case 65://Creature target
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 66://Friend hit
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 67://Fight
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 68://Hello????
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 69://Alarm
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 70://Flee
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ case 71://Should Attack
+ if(!selectCompare(comp,0,select.i)) return false;
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ }
+
+ return true;
+ }
+
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
const ESM::DialInfo::SelectStruct& select) const
{
@@ -124,58 +264,173 @@ namespace MWDialogue
{
char comp = select.selectRule[4];
std::string name = select.selectRule.substr (5);
-
- // TODO types 4, 5, 6, 7, 8, 9, A, B, C
+ std::string function = select.selectRule.substr(1,2);
switch (type)
{
- case '1': // function
+ case '1': // function
- return false; // TODO implement functions
+ return true; // TODO implement functions
- case '2': // global
+ case '2': // global
- if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
- select.type==ESM::VT_Long)
- {
- if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
- return false;
- }
- else if (select.type==ESM::VT_Float)
- {
- if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
- return false;
- }
- else
- throw std::runtime_error (
- "unsupported variable type in dialogue info select");
+ if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
+ select.type==ESM::VT_Long)
+ {
+ if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
+ return false;
+ }
+ else if (select.type==ESM::VT_Float)
+ {
+ if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
- return true;
+ return true;
- case '3': // local
+ case '3': // local
- if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
- select.type==ESM::VT_Long)
- {
- if (!checkLocal (comp, toLower (name), select.i, actor,
- mEnvironment.mWorld->getStore()))
- return false;
- }
- else if (select.type==ESM::VT_Float)
- {
- if (!checkLocal (comp, toLower (name), select.f, actor,
- mEnvironment.mWorld->getStore()))
- return false;
- }
- else
- throw std::runtime_error (
- "unsupported variable type in dialogue info select");
+ if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
+ select.type==ESM::VT_Long)
+ {
+ if (!checkLocal (comp, toLower (name), select.i, actor,
+ mEnvironment.mWorld->getStore()))
+ return false;
+ }
+ else if (select.type==ESM::VT_Float)
+ {
+ if (!checkLocal (comp, toLower (name), select.f, actor,
+ mEnvironment.mWorld->getStore()))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
- return true;
+ return true;
- default:
+ case '4'://journal
+ if(select.type==ESM::VT_Int)
+ {
+ if(!selectCompare(comp,mEnvironment.mJournal->getJournalIndex(toLower(name)),select.i)) return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+
+ return true;
+
+ case '5'://item
+ {
+ MWWorld::Ptr player = mEnvironment.mWorld->getPlayer().getPlayer();
+ MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player);
+
+ int sum = 0;
+
+ for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
+ if (iter->getCellRef().refID==name)
+ sum += iter->getRefData().getCount();
+ if(!selectCompare(comp,sum,select.i)) return false;
+ }
+
+ return true;
+
+
+ case '6'://dead
+ if(!selectCompare(comp,0,select.i)) return false;
+
+ case '7':// not ID
+ if(select.type==ESM::VT_String ||select.type==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string
+ {
+ int isID = int(toLower(name)==toLower(MWWorld::Class::get (actor).getId (actor)));
+ if (selectCompare(comp,!isID,select.i)) return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+
+ return true;
+
+ case '8':// not faction
+ if(select.type==ESM::VT_Int)
+ {
+ ESMS::LiveCellRef* npc = actor.get();
+ int isFaction = int(toLower(npc->base->faction) == toLower(name));
+ if(selectCompare(comp,!isFaction,select.i))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+
+ return true;
+
+ case '9':// not class
+ if(select.type==ESM::VT_Int)
+ {
+ ESMS::LiveCellRef* npc = actor.get();
+ int isClass = int(toLower(npc->base->cls) == toLower(name));
+ if(selectCompare(comp,!isClass,select.i))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+
+ return true;
+
+ case 'A'://not Race
+ if(select.type==ESM::VT_Int)
+ {
+ ESMS::LiveCellRef* npc = actor.get();
+ int isRace = int(toLower(npc->base->race) == toLower(name));
+ if(selectCompare(comp,!isRace,select.i))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+
+ return true;
- std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
+ case 'B'://not Cell
+ if(select.type==ESM::VT_Int)
+ {
+ int isCell = int(toLower(actor.getCell()->cell->name) == toLower(name));
+ if(selectCompare(comp,!isCell,select.i))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+ return true;
+
+ case 'C'://not local
+ if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
+ select.type==ESM::VT_Long)
+ {
+ if (checkLocal (comp, toLower (name), select.i, actor,
+ mEnvironment.mWorld->getStore()))
+ return false;
+ }
+ else if (select.type==ESM::VT_Float)
+ {
+ if (checkLocal (comp, toLower (name), select.f, actor,
+ mEnvironment.mWorld->getStore()))
+ return false;
+ }
+ else
+ throw std::runtime_error (
+ "unsupported variable type in dialogue info select");
+ return true;
+
+
+ default:
+
+ std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
}
}
@@ -189,6 +444,10 @@ namespace MWDialogue
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
return false;
+ //PC Faction
+ if(!info.pcFaction.empty()) return false;
+
+ //NPC race
if (!info.race.empty())
{
ESMS::LiveCellRef *cellRef = actor.get();
@@ -200,6 +459,7 @@ namespace MWDialogue
return false;
}
+ //NPC class
if (!info.clas.empty())
{
ESMS::LiveCellRef *cellRef = actor.get();
@@ -211,6 +471,7 @@ namespace MWDialogue
return false;
}
+ //NPC faction
if (!info.npcFaction.empty())
{
ESMS::LiveCellRef *cellRef = actor.get();
@@ -220,66 +481,320 @@ namespace MWDialogue
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
return false;
+
+ //check NPC rank
+ if(cellRef->base->npdt52.gold != -10)
+ {
+ if(cellRef->base->npdt52.rank < info.data.rank) return false;
+ }
+ else
+ {
+ if(cellRef->base->npdt12.rank < info.data.rank) return false;
+ }
}
// TODO check player faction
+ //check gender
+ ESMS::LiveCellRef* npc = actor.get();
+ if(npc->base->flags&npc->base->Female)
+ {
+ if(static_cast (info.data.gender)==0) return false;
+ }
+ else
+ {
+ if(static_cast (info.data.gender)==1) return false;
+ }
+
+
// check cell
if (!info.cell.empty())
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
return false;
// TODO check DATAstruct
-
for (std::vector::const_iterator iter (info.selects.begin());
iter != info.selects.end(); ++iter)
if (!isMatching (actor, *iter))
return false;
- std::cout
- << "unchecked entries:" << std::endl
- << " player faction: " << info.pcFaction << std::endl
- << " disposition: " << info.data.disposition << std::endl
- << " NPC rank: " << static_cast (info.data.rank) << std::endl
- << " gender: " << static_cast (info.data.gender) << std::endl
- << " PC rank: " << static_cast (info.data.PCrank) << std::endl;
-
return true;
}
- DialogueManager::DialogueManager (MWWorld::Environment& environment) : mEnvironment (environment) {}
+ DialogueManager::DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions) :
+ mEnvironment (environment),mCompilerContext (MWScript::CompilerContext::Type_Dialgoue, environment),
+ mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
+ {
+ mChoice = -1;
+ mIsInChoice = false;
+ mCompilerContext.setExtensions (&extensions);
+ }
+
+ void DialogueManager::addTopic(std::string topic)
+ {
+ knownTopics[toLower(topic)] = true;
+ }
+
+ void DialogueManager::parseText(std::string text)
+ {
+ std::list::iterator it;
+ for(it = actorKnownTopics.begin();it != actorKnownTopics.end();it++)
+ {
+ size_t pos = find_str_ci(text,*it,0);
+ if(pos !=std::string::npos)
+ {
+ if(pos==0)
+ {
+ knownTopics[*it] = true;
+ }
+ else if(text.substr(pos -1,1) == " ")
+ {
+ knownTopics[*it] = true;
+ }
+ }
+ }
+ updateTopics();
+ }
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
{
- std::cout << "talking with " << MWWorld::Class::get (actor).getName (actor) << std::endl;
+ mChoice = -1;
+ mIsInChoice = false;
- const ESM::Dialogue *dialogue = mEnvironment.mWorld->getStore().dialogs.find ("hello");
+ mActor = actor;
- for (std::vector::const_iterator iter (dialogue->mInfo.begin());
- iter!=dialogue->mInfo.end(); ++iter)
+ mDialogueMap.clear();
+ actorKnownTopics.clear();
+ ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
+ for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
{
- if (isMatching (actor, *iter))
+ mDialogueMap[it->first] = it->second;
+ }
+
+ //initialise the GUI
+ mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ win->startDialogue(MWWorld::Class::get (actor).getName (actor));
+
+ //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
+ updateTopics();
+
+ //greeting
+ bool greetingFound = false;
+ //ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
+ for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
+ {
+ ESM::Dialogue ndialogue = it->second;
+ if(ndialogue.type == ESM::Dialogue::Greeting)
{
- // start dialogue
- std::cout << "found matching info record" << std::endl;
+ if (greetingFound) break;
+ for (std::vector::const_iterator iter (it->second.mInfo.begin());
+ iter!=it->second.mInfo.end(); ++iter)
+ {
+ if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true))
+ {
+ if (!iter->sound.empty())
+ {
+ // TODO play sound
+ }
+
+ std::string text = iter->response;
+ parseText(text);
+ win->addText(iter->response);
+ executeScript(iter->resultScript);
+ greetingFound = true;
+ mLastTopic = it->first;
+ mLastDialogue = *iter;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ bool DialogueManager::compile (const std::string& cmd,std::vector& code)
+ {
+ try
+ {
+ mErrorHandler.reset();
+
+ std::istringstream input (cmd + "\n");
+
+ Compiler::Scanner scanner (mErrorHandler, input, mCompilerContext.getExtensions());
+
+ Compiler::Locals locals;
+
+ std::string actorScript = MWWorld::Class::get (mActor).getScript (mActor);
+
+ if (!actorScript.empty())
+ {
+ // grab local variables from actor's script, if available.
+ locals = mEnvironment.mScriptManager->getLocals (actorScript);
+ }
+
+ Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false);
+
+ scanner.scan (parser);
+ if(mErrorHandler.isGood())
+ {
+ parser.getCode(code);
+ return true;
+ }
+ return false;
+ }
+ catch (const Compiler::SourceException& error)
+ {
+ // error has already been reported via error handler
+ }
+ catch (const std::exception& error)
+ {
+ printError (std::string ("An exception has been thrown: ") + error.what());
+ }
- std::cout << "response: " << iter->response << std::endl;
+ return false;
+ }
- if (!iter->sound.empty())
+ void DialogueManager::executeScript(std::string script)
+ {
+ std::vector code;
+ if(compile(script,code))
+ {
+ try
+ {
+ MWScript::InterpreterContext interpreterContext(mEnvironment,&mActor.getRefData().getLocals(),mActor);
+ Interpreter::Interpreter interpreter;
+ MWScript::installOpcodes (interpreter);
+ interpreter.run (&code[0], code.size(), interpreterContext);
+ }
+ catch (const std::exception& error)
+ {
+ printError (std::string ("An exception has been thrown: ") + error.what());
+ }
+ }
+ }
+
+ void DialogueManager::updateTopics()
+ {
+ std::list keywordList;
+ int choice = mChoice;
+ mChoice = -1;
+ actorKnownTopics.clear();
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ ESMS::RecListT::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
+ for(ESMS::RecListT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
+ {
+ ESM::Dialogue ndialogue = it->second;
+ if(ndialogue.type == ESM::Dialogue::Topic)
+ {
+ for (std::vector::const_iterator iter (it->second.mInfo.begin());
+ iter!=it->second.mInfo.end(); ++iter)
{
- // TODO play sound
+ if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
+ {
+ actorKnownTopics.push_back(it->first);
+ //does the player know the topic?
+ if(knownTopics.find(toLower(it->first)) != knownTopics.end())
+ {
+ keywordList.push_back(it->first);
+ break;
+ }
+ }
}
+ }
+ }
+ win->setKeywords(keywordList);
+ mChoice = choice;
+ }
- if (!iter->resultScript.empty())
+ void DialogueManager::keywordSelected(std::string keyword)
+ {
+ if(!mIsInChoice)
+ {
+ if(mDialogueMap.find(keyword) != mDialogueMap.end())
+ {
+ ESM::Dialogue ndialogue = mDialogueMap[keyword];
+ if(ndialogue.type == ESM::Dialogue::Topic)
{
- std::cout << "script: " << iter->resultScript << std::endl;
- // TODO execute script
+ for (std::vector::const_iterator iter = ndialogue.mInfo.begin();
+ iter!=ndialogue.mInfo.end(); ++iter)
+ {
+ if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
+ {
+ std::string text = iter->response;
+ std::string script = iter->resultScript;
+
+ parseText(text);
+
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ win->addTitle(keyword);
+ win->addText(iter->response);
+
+ executeScript(script);
+
+ mLastTopic = keyword;
+ mLastDialogue = *iter;
+ break;
+ }
+ }
}
+ }
+ }
- mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
- break;
+ updateTopics();
+ }
+
+ void DialogueManager::goodbyeSelected()
+ {
+ mEnvironment.mInputManager->setGuiMode(MWGui::GM_Game);
+ }
+
+ void DialogueManager::questionAnswered(std::string answere)
+ {
+ if(mChoiceMap.find(answere) != mChoiceMap.end())
+ {
+ mChoice = mChoiceMap[answere];
+
+ std::vector::const_iterator iter;
+ if(mDialogueMap.find(mLastTopic) != mDialogueMap.end())
+ {
+ ESM::Dialogue ndialogue = mDialogueMap[mLastTopic];
+ if(ndialogue.type == ESM::Dialogue::Topic)
+ {
+ for (std::vector::const_iterator iter = ndialogue.mInfo.begin();
+ iter!=ndialogue.mInfo.end(); ++iter)
+ {
+ if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
+ {
+ mChoiceMap.clear();
+ mChoice = -1;
+ mIsInChoice = false;
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ std::string text = iter->response;
+ parseText(text);
+ win->addText(text);
+ executeScript(iter->resultScript);
+ mLastTopic = mLastTopic;
+ mLastDialogue = *iter;
+ break;
+ }
+ }
+ }
}
+ updateTopics();
}
}
+ void DialogueManager::printError(std::string error)
+ {
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ win->addText(error);
+ }
+
+ void DialogueManager::askQuestion(std::string question, int choice)
+ {
+ MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
+ win->askQuestion(question);
+ mChoiceMap[question] = choice;
+ mIsInChoice = true;
+ }
}
diff --git a/apps/openmw/mwdialogue/dialoguemanager.hpp b/apps/openmw/mwdialogue/dialoguemanager.hpp
index 5b6b26240..260d8e339 100644
--- a/apps/openmw/mwdialogue/dialoguemanager.hpp
+++ b/apps/openmw/mwdialogue/dialoguemanager.hpp
@@ -3,7 +3,13 @@
#include
+#include
+#include "../mwscript/compilercontext.hpp"
+#include "../mwscript/interpretercontext.hpp"
+#include
+
#include "../mwworld/ptr.hpp"
+#include