forked from mirror/openmw-tes3mp
Merge branch 'master' into mygui
This commit is contained in:
commit
66baf9ec81
37 changed files with 1307 additions and 474 deletions
|
@ -18,7 +18,7 @@ include (OpenMWMacros)
|
||||||
# Version
|
# Version
|
||||||
|
|
||||||
set (OPENMW_VERSION_MAJOR 0)
|
set (OPENMW_VERSION_MAJOR 0)
|
||||||
set (OPENMW_VERSION_MINOR 12)
|
set (OPENMW_VERSION_MINOR 13)
|
||||||
set (OPENMW_VERSION_RELEASE 0)
|
set (OPENMW_VERSION_RELEASE 0)
|
||||||
|
|
||||||
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
@ -185,6 +185,11 @@ endif (APPLE)
|
||||||
|
|
||||||
# Dependencies
|
# 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(OGRE REQUIRED)
|
||||||
find_package(MyGUI REQUIRED)
|
find_package(MyGUI REQUIRED)
|
||||||
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
|
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_NAME "openmw")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher")
|
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")
|
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
|
||||||
|
|
||||||
|
@ -451,7 +456,9 @@ if (WIN32)
|
||||||
endforeach(d)
|
endforeach(d)
|
||||||
|
|
||||||
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
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})
|
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ void DataFilesPage::setupDataFiles()
|
||||||
|
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle("Error detecting Morrowind installation");
|
msgBox.setWindowTitle("Error detecting Morrowind installation");
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
||||||
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
||||||
The directory containing the Data Files was not found.<br><br> \
|
The directory containing the Data Files was not found.<br><br> \
|
||||||
|
@ -279,72 +279,79 @@ void DataFilesPage::setupDataFiles()
|
||||||
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
|
const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp");
|
||||||
|
|
||||||
for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) {
|
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<std::string>());
|
try {
|
||||||
fileReader.open(iter->second.string());
|
ESMReader fileReader;
|
||||||
|
QStringList availableMasters; // Will contain all found masters
|
||||||
|
|
||||||
// First we fill the availableMasters and the mMastersWidget
|
fileReader.setEncoding(variables["encoding"].as<std::string>());
|
||||||
ESMReader::MasterList mlist = fileReader.getMasters();
|
fileReader.open(iter->second.string());
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
// First we fill the availableMasters and the mMastersWidget
|
||||||
const QString currentMaster = QString::fromStdString(mlist[i].name);
|
ESMReader::MasterList mlist = fileReader.getMasters();
|
||||||
availableMasters.append(currentMaster);
|
|
||||||
|
|
||||||
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
|
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
||||||
|
const QString currentMaster = QString::fromStdString(mlist[i].name);
|
||||||
|
availableMasters.append(currentMaster);
|
||||||
|
|
||||||
if (itemList.isEmpty()) { // Master is not yet in the widget
|
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
|
||||||
mMastersWidget->insertRow(i);
|
|
||||||
|
|
||||||
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
|
if (itemList.isEmpty()) { // Master is not yet in the widget
|
||||||
item->setForeground(Qt::red);
|
mMastersWidget->insertRow(i);
|
||||||
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
|
|
||||||
|
|
||||||
mMastersWidget->setItem(i, 0, item);
|
QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
|
||||||
|
item->setForeground(Qt::red);
|
||||||
|
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
|
||||||
|
|
||||||
|
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
|
// Now we put the current plugin in the mDataFilesModel under its masters
|
||||||
QStandardItem *parent = new QStandardItem(availableMasters.join(","));
|
QStandardItem *parent = new QStandardItem(availableMasters.join(","));
|
||||||
|
|
||||||
QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
|
QString fileName = QString::fromStdString(boost::filesystem::path (iter->second.filename()).string());
|
||||||
QStandardItem *child = new QStandardItem(fileName);
|
QStandardItem *child = new QStandardItem(fileName);
|
||||||
|
|
||||||
// Tooltip information
|
// Tooltip information
|
||||||
QString author = QString::fromStdString(fileReader.getAuthor());
|
QString author = QString::fromStdString(fileReader.getAuthor());
|
||||||
float version = fileReader.getFVer();
|
float version = fileReader.getFVer();
|
||||||
QString description = QString::fromStdString(fileReader.getDesc());
|
QString description = QString::fromStdString(fileReader.getDesc());
|
||||||
|
|
||||||
// For the date created/modified
|
// For the date created/modified
|
||||||
QFileInfo fi(QString::fromStdString(iter->second.string()));
|
QFileInfo fi(QString::fromStdString(iter->second.string()));
|
||||||
|
|
||||||
QString toolTip= QString("<b>Author:</b> %1<br/> \
|
QString toolTip= QString("<b>Author:</b> %1<br/> \
|
||||||
<b>Version:</b> %2<br/><br/> \
|
<b>Version:</b> %2<br/><br/> \
|
||||||
<b>Description:</b><br/> \
|
<b>Description:</b><br/> \
|
||||||
%3<br/><br/> \
|
%3<br/><br/> \
|
||||||
<b>Created on:</b> %4<br/> \
|
<b>Created on:</b> %4<br/> \
|
||||||
<b>Last modified:</b> %5")
|
<b>Last modified:</b> %5")
|
||||||
.arg(author)
|
.arg(author)
|
||||||
.arg(version)
|
.arg(version)
|
||||||
.arg(description)
|
.arg(description)
|
||||||
.arg(fi.created().toString(Qt::TextDate))
|
.arg(fi.created().toString(Qt::TextDate))
|
||||||
.arg(fi.lastModified().toString(Qt::TextDate));
|
.arg(fi.lastModified().toString(Qt::TextDate));
|
||||||
|
|
||||||
child->setToolTip(toolTip);
|
child->setToolTip(toolTip);
|
||||||
|
|
||||||
const QList<QStandardItem*> masterList = mDataFilesModel->findItems(availableMasters.join(","));
|
const QList<QStandardItem*> masterList = mDataFilesModel->findItems(availableMasters.join(","));
|
||||||
|
|
||||||
if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
|
if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel
|
||||||
parent->appendRow(child);
|
parent->appendRow(child);
|
||||||
mDataFilesModel->appendRow(parent);
|
mDataFilesModel->appendRow(parent);
|
||||||
} else {
|
} else {
|
||||||
// Masters node exists, append current plugin
|
// Masters node exists, append current plugin
|
||||||
foreach (QStandardItem *currentItem, masterList) {
|
foreach (QStandardItem *currentItem, masterList) {
|
||||||
currentItem->appendRow(child);
|
currentItem->appendRow(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch(std::runtime_error &e) {
|
||||||
|
// An error occurred while reading the .esp
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ add_definitions(${SOUND_DEFINE})
|
||||||
|
|
||||||
target_link_libraries(openmw
|
target_link_libraries(openmw
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
${OGRE_STATIC_PLUGINS}
|
${OGRE_STATIC_PLUGINS}
|
||||||
${OIS_LIBRARIES}
|
${OIS_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
|
@ -92,6 +92,11 @@ target_link_libraries(openmw
|
||||||
components
|
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)
|
if(APPLE)
|
||||||
find_library(CARBON_FRAMEWORK Carbon)
|
find_library(CARBON_FRAMEWORK Carbon)
|
||||||
target_link_libraries(openmw ${CARBON_FRAMEWORK})
|
target_link_libraries(openmw ${CARBON_FRAMEWORK})
|
||||||
|
|
|
@ -60,7 +60,7 @@ void OMW::Engine::executeLocalScripts()
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext (mEnvironment,
|
MWScript::InterpreterContext interpreterContext (mEnvironment,
|
||||||
&script.second.getRefData().getLocals(), script.second);
|
&script.second.getRefData().getLocals(), script.second);
|
||||||
mScriptManager->run (script.first, interpreterContext);
|
mEnvironment.mScriptManager->run (script.first, interpreterContext);
|
||||||
|
|
||||||
if (mEnvironment.mWorld->hasCellChanged())
|
if (mEnvironment.mWorld->hasCellChanged())
|
||||||
break;
|
break;
|
||||||
|
@ -182,7 +182,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
, mCompileAll (false)
|
, mCompileAll (false)
|
||||||
, mReportFocus (false)
|
, mReportFocus (false)
|
||||||
, mFocusTDiff (0)
|
, mFocusTDiff (0)
|
||||||
, mScriptManager (0)
|
|
||||||
, mScriptContext (0)
|
, mScriptContext (0)
|
||||||
, mFSStrict (false)
|
, mFSStrict (false)
|
||||||
, mCfgMgr(configurationManager)
|
, mCfgMgr(configurationManager)
|
||||||
|
@ -199,7 +198,7 @@ OMW::Engine::~Engine()
|
||||||
delete mEnvironment.mMechanicsManager;
|
delete mEnvironment.mMechanicsManager;
|
||||||
delete mEnvironment.mDialogueManager;
|
delete mEnvironment.mDialogueManager;
|
||||||
delete mEnvironment.mJournal;
|
delete mEnvironment.mJournal;
|
||||||
delete mScriptManager;
|
delete mEnvironment.mScriptManager;
|
||||||
delete mScriptContext;
|
delete mScriptContext;
|
||||||
delete mOgre;
|
delete mOgre;
|
||||||
}
|
}
|
||||||
|
@ -348,18 +347,18 @@ void OMW::Engine::go()
|
||||||
mEnvironment);
|
mEnvironment);
|
||||||
mScriptContext->setExtensions (&mExtensions);
|
mScriptContext->setExtensions (&mExtensions);
|
||||||
|
|
||||||
mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts,
|
mEnvironment.mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(),
|
||||||
*mScriptContext);
|
mVerboseScripts, *mScriptContext);
|
||||||
|
|
||||||
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
|
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
|
||||||
*mScriptManager);
|
*mEnvironment.mScriptManager);
|
||||||
|
|
||||||
// Create game mechanics system
|
// Create game mechanics system
|
||||||
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
|
mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment);
|
||||||
|
|
||||||
// Create dialog system
|
// Create dialog system
|
||||||
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
|
mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment);
|
||||||
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment);
|
mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment,mExtensions);
|
||||||
|
|
||||||
// load cell
|
// load cell
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
|
@ -393,7 +392,7 @@ void OMW::Engine::go()
|
||||||
// scripts
|
// scripts
|
||||||
if (mCompileAll)
|
if (mCompileAll)
|
||||||
{
|
{
|
||||||
std::pair<int, int> result = mScriptManager->compileAll();
|
std::pair<int, int> result = mEnvironment.mScriptManager->compileAll();
|
||||||
|
|
||||||
if (result.first)
|
if (result.first)
|
||||||
std::cout
|
std::cout
|
||||||
|
@ -438,7 +437,7 @@ void OMW::Engine::activate()
|
||||||
if (!script.empty())
|
if (!script.empty())
|
||||||
{
|
{
|
||||||
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
|
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
|
||||||
mScriptManager->run (script, interpreterContext);
|
mEnvironment.mScriptManager->run (script, interpreterContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!interpreterContext.hasActivationBeenHandled())
|
if (!interpreterContext.hasActivationBeenHandled())
|
||||||
|
|
|
@ -78,10 +78,9 @@ namespace OMW
|
||||||
std::string mFocusName;
|
std::string mFocusName;
|
||||||
|
|
||||||
MWWorld::Environment mEnvironment;
|
MWWorld::Environment mEnvironment;
|
||||||
MWScript::ScriptManager *mScriptManager;
|
|
||||||
Compiler::Extensions mExtensions;
|
Compiler::Extensions mExtensions;
|
||||||
Compiler::Context *mScriptContext;
|
Compiler::Context *mScriptContext;
|
||||||
|
|
||||||
|
|
||||||
Files::Collections mFileCollections;
|
Files::Collections mFileCollections;
|
||||||
bool mFSStrict;
|
bool mFSStrict;
|
||||||
|
|
|
@ -9,16 +9,36 @@
|
||||||
|
|
||||||
#include <components/esm_store/store.hpp>
|
#include <components/esm_store/store.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
#include "../mwworld/refdata.hpp"
|
#include "../mwworld/refdata.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
#include "../mwinput/inputmanager.hpp"
|
#include "../mwinput/inputmanager.hpp"
|
||||||
|
#include "../mwgui/dialogue.hpp"
|
||||||
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
|
||||||
|
#include "journal.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../mwscript/extensions.hpp"
|
||||||
|
#include "../mwscript/scriptmanager.hpp"
|
||||||
|
|
||||||
|
#include <components/compiler/exception.hpp>
|
||||||
|
#include <components/compiler/errorhandler.hpp>
|
||||||
|
#include <components/compiler/scanner.hpp>
|
||||||
|
#include <components/compiler/locals.hpp>
|
||||||
|
#include <components/compiler/output.hpp>
|
||||||
|
#include <components/interpreter/interpreter.hpp>
|
||||||
|
|
||||||
|
#include "../mwscript/compilercontext.hpp"
|
||||||
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
|
#include <components/compiler/scriptparser.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::string toLower (const std::string& name)
|
std::string toLower (const std::string& name)
|
||||||
|
@ -31,17 +51,18 @@ namespace
|
||||||
return lowerCase;
|
return lowerCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
bool selectCompare (char comp, T1 value1, T2 value2)
|
bool selectCompare (char comp, T1 value1, T2 value2)
|
||||||
{
|
{
|
||||||
switch (comp)
|
switch (comp)
|
||||||
{
|
{
|
||||||
case '0': return value1==value2;
|
case '0': return value1==value2;
|
||||||
case '1': return value1!=value2;
|
case '1': return value1!=value2;
|
||||||
case '2': return value1>value2;
|
case '2': return value1>value2;
|
||||||
case '3': return value1>=value2;
|
case '3': return value1>=value2;
|
||||||
case '4': return value1<value2;
|
case '4': return value1<value2;
|
||||||
case '5': return value1<=value2;
|
case '5': return value1<=value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error ("unknown compare type in dialogue info select");
|
throw std::runtime_error ("unknown compare type in dialogue info select");
|
||||||
|
@ -87,26 +108,26 @@ namespace
|
||||||
{
|
{
|
||||||
switch (world.getGlobalVariableType (name))
|
switch (world.getGlobalVariableType (name))
|
||||||
{
|
{
|
||||||
case 's':
|
case 's':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
|
|
||||||
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
|
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
|
||||||
|
|
||||||
case ' ':
|
case ' ':
|
||||||
|
|
||||||
world.getGlobalVariable (name); // trigger exception
|
world.getGlobalVariable (name); // trigger exception
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
throw std::runtime_error ("unsupported gobal variable type");
|
throw std::runtime_error ("unsupported gobal variable type");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -115,6 +136,125 @@ namespace
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//helper function
|
||||||
|
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
|
||||||
|
{
|
||||||
|
return toLower(str).find(toLower(substr),pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo::SelectStruct>::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<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 40://PC Common Disease
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 41://PC Blight Disease
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 43://PC Crime level
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 46://Same faction
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 48://Detected
|
||||||
|
if(!selectCompare<int,int>(comp,1,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 49://Alarmed
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 50://choice
|
||||||
|
|
||||||
|
if(choice)
|
||||||
|
{
|
||||||
|
if(!selectCompare<int,int>(comp,mChoice,select.i)) return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 60://PC Vampire
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 61://Level
|
||||||
|
if(!selectCompare<int,int>(comp,1,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 62://Attacked
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 63://Talked to PC
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 64://PC Health
|
||||||
|
if(!selectCompare<int,int>(comp,50,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 65://Creature target
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 66://Friend hit
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 67://Fight
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 68://Hello????
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 69://Alarm
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 70://Flee
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 71://Should Attack
|
||||||
|
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
|
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
|
||||||
const ESM::DialInfo::SelectStruct& select) const
|
const ESM::DialInfo::SelectStruct& select) const
|
||||||
{
|
{
|
||||||
|
@ -124,58 +264,173 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
char comp = select.selectRule[4];
|
char comp = select.selectRule[4];
|
||||||
std::string name = select.selectRule.substr (5);
|
std::string name = select.selectRule.substr (5);
|
||||||
|
std::string function = select.selectRule.substr(1,2);
|
||||||
// TODO types 4, 5, 6, 7, 8, 9, A, B, C
|
|
||||||
|
|
||||||
switch (type)
|
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 ||
|
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
||||||
select.type==ESM::VT_Long)
|
select.type==ESM::VT_Long)
|
||||||
{
|
{
|
||||||
if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
|
if (!checkGlobal (comp, toLower (name), select.i, *mEnvironment.mWorld))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (select.type==ESM::VT_Float)
|
else if (select.type==ESM::VT_Float)
|
||||||
{
|
{
|
||||||
if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
|
if (!checkGlobal (comp, toLower (name), select.f, *mEnvironment.mWorld))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"unsupported variable type in dialogue info select");
|
"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 ||
|
if (select.type==ESM::VT_Short || select.type==ESM::VT_Int ||
|
||||||
select.type==ESM::VT_Long)
|
select.type==ESM::VT_Long)
|
||||||
{
|
{
|
||||||
if (!checkLocal (comp, toLower (name), select.i, actor,
|
if (!checkLocal (comp, toLower (name), select.i, actor,
|
||||||
mEnvironment.mWorld->getStore()))
|
mEnvironment.mWorld->getStore()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (select.type==ESM::VT_Float)
|
else if (select.type==ESM::VT_Float)
|
||||||
{
|
{
|
||||||
if (!checkLocal (comp, toLower (name), select.f, actor,
|
if (!checkLocal (comp, toLower (name), select.f, actor,
|
||||||
mEnvironment.mWorld->getStore()))
|
mEnvironment.mWorld->getStore()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"unsupported variable type in dialogue info select");
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
case '4'://journal
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
if(!selectCompare<int,int>(comp,mEnvironment.mJournal->getJournalIndex(toLower(name)),select.i)) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl;
|
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<int,int>(comp,sum,select.i)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
case '6'://dead
|
||||||
|
if(!selectCompare<int,int>(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<int,int>(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<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isFaction = int(toLower(npc->base->faction) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(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<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isClass = int(toLower(npc->base->cls) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(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<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
int isRace = int(toLower(npc->base->race) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(comp,!isRace,select.i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error (
|
||||||
|
"unsupported variable type in dialogue info select");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 'B'://not Cell
|
||||||
|
if(select.type==ESM::VT_Int)
|
||||||
|
{
|
||||||
|
int isCell = int(toLower(actor.getCell()->cell->name) == toLower(name));
|
||||||
|
if(selectCompare<int,int>(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))
|
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
//PC Faction
|
||||||
|
if(!info.pcFaction.empty()) return false;
|
||||||
|
|
||||||
|
//NPC race
|
||||||
if (!info.race.empty())
|
if (!info.race.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -200,6 +459,7 @@ namespace MWDialogue
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NPC class
|
||||||
if (!info.clas.empty())
|
if (!info.clas.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -211,6 +471,7 @@ namespace MWDialogue
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NPC faction
|
||||||
if (!info.npcFaction.empty())
|
if (!info.npcFaction.empty())
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||||
|
@ -220,66 +481,320 @@ namespace MWDialogue
|
||||||
|
|
||||||
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
|
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
|
||||||
return false;
|
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
|
// TODO check player faction
|
||||||
|
|
||||||
|
//check gender
|
||||||
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||||
|
if(npc->base->flags&npc->base->Female)
|
||||||
|
{
|
||||||
|
if(static_cast<int> (info.data.gender)==0) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(static_cast<int> (info.data.gender)==1) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// check cell
|
// check cell
|
||||||
if (!info.cell.empty())
|
if (!info.cell.empty())
|
||||||
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
|
if (mEnvironment.mWorld->getPlayer().getPlayer().getCell()->cell->name != info.cell)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO check DATAstruct
|
// TODO check DATAstruct
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
||||||
iter != info.selects.end(); ++iter)
|
iter != info.selects.end(); ++iter)
|
||||||
if (!isMatching (actor, *iter))
|
if (!isMatching (actor, *iter))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::cout
|
|
||||||
<< "unchecked entries:" << std::endl
|
|
||||||
<< " player faction: " << info.pcFaction << std::endl
|
|
||||||
<< " disposition: " << info.data.disposition << std::endl
|
|
||||||
<< " NPC rank: " << static_cast<int> (info.data.rank) << std::endl
|
|
||||||
<< " gender: " << static_cast<int> (info.data.gender) << std::endl
|
|
||||||
<< " PC rank: " << static_cast<int> (info.data.PCrank) << std::endl;
|
|
||||||
|
|
||||||
return true;
|
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<std::string>::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)
|
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<ESM::DialInfo>::const_iterator iter (dialogue->mInfo.begin());
|
mDialogueMap.clear();
|
||||||
iter!=dialogue->mInfo.end(); ++iter)
|
actorKnownTopics.clear();
|
||||||
|
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::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<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = it->second;
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Greeting)
|
||||||
{
|
{
|
||||||
// start dialogue
|
if (greetingFound) break;
|
||||||
std::cout << "found matching info record" << std::endl;
|
for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
|
||||||
|
iter!=it->second.mInfo.end(); ++iter)
|
||||||
std::cout << "response: " << iter->response << std::endl;
|
|
||||||
|
|
||||||
if (!iter->sound.empty())
|
|
||||||
{
|
{
|
||||||
// TODO play sound
|
if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true))
|
||||||
}
|
{
|
||||||
|
if (!iter->sound.empty())
|
||||||
|
{
|
||||||
|
// TODO play sound
|
||||||
|
}
|
||||||
|
|
||||||
if (!iter->resultScript.empty())
|
std::string text = iter->response;
|
||||||
{
|
parseText(text);
|
||||||
std::cout << "script: " << iter->resultScript << std::endl;
|
win->addText(iter->response);
|
||||||
// TODO execute script
|
executeScript(iter->resultScript);
|
||||||
|
greetingFound = true;
|
||||||
|
mLastTopic = it->first;
|
||||||
|
mLastDialogue = *iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::executeScript(std::string script)
|
||||||
|
{
|
||||||
|
std::vector<Interpreter::Type_Code> 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<std::string> keywordList;
|
||||||
|
int choice = mChoice;
|
||||||
|
mChoice = -1;
|
||||||
|
actorKnownTopics.clear();
|
||||||
|
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
|
||||||
|
ESMS::RecListT<ESM::Dialogue>::MapType dialogueList = mEnvironment.mWorld->getStore().dialogs.list;
|
||||||
|
for(ESMS::RecListT<ESM::Dialogue>::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++)
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = it->second;
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Topic)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::const_iterator iter (it->second.mInfo.begin());
|
||||||
|
iter!=it->second.mInfo.end(); ++iter)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<ESM::DialInfo>::const_iterator iter;
|
||||||
|
if(mDialogueMap.find(mLastTopic) != mDialogueMap.end())
|
||||||
|
{
|
||||||
|
ESM::Dialogue ndialogue = mDialogueMap[mLastTopic];
|
||||||
|
if(ndialogue.type == ESM::Dialogue::Topic)
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::DialInfo>::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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,13 @@
|
||||||
|
|
||||||
#include <components/esm/loadinfo.hpp>
|
#include <components/esm/loadinfo.hpp>
|
||||||
|
|
||||||
|
#include <components/compiler/streamerrorhandler.hpp>
|
||||||
|
#include "../mwscript/compilercontext.hpp"
|
||||||
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
|
#include <components/compiler/output.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -20,12 +26,48 @@ namespace MWDialogue
|
||||||
|
|
||||||
bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const;
|
bool isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const;
|
||||||
|
|
||||||
|
bool functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice);
|
||||||
|
|
||||||
|
void parseText(std::string text);
|
||||||
|
|
||||||
|
void updateTopics();
|
||||||
|
|
||||||
|
std::map<std::string,ESM::Dialogue> mDialogueMap;
|
||||||
|
std::map<std::string,bool> knownTopics;// Those are the topics the player knows.
|
||||||
|
std::list<std::string> actorKnownTopics;
|
||||||
|
|
||||||
|
MWScript::CompilerContext mCompilerContext;
|
||||||
|
std::ostream mErrorStream;
|
||||||
|
Compiler::StreamErrorHandler mErrorHandler;
|
||||||
|
|
||||||
|
|
||||||
|
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
||||||
|
void executeScript(std::string script);
|
||||||
|
MWWorld::Ptr mActor;
|
||||||
|
|
||||||
|
void printError(std::string error);
|
||||||
|
|
||||||
|
int mChoice;
|
||||||
|
std::map<std::string,int> mChoiceMap;
|
||||||
|
std::string mLastTopic;
|
||||||
|
ESM::DialInfo mLastDialogue;
|
||||||
|
bool mIsInChoice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DialogueManager (MWWorld::Environment& environment);
|
DialogueManager (MWWorld::Environment& environment,const Compiler::Extensions& extensions);
|
||||||
|
|
||||||
void startDialogue (const MWWorld::Ptr& actor);
|
void startDialogue (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
void addTopic(std::string topic);
|
||||||
|
|
||||||
|
void askQuestion(std::string question,int choice);
|
||||||
|
|
||||||
|
//calbacks for the GUI
|
||||||
|
void keywordSelected(std::string keyword);
|
||||||
|
void goodbyeSelected();
|
||||||
|
void questionAnswered(std::string answere);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
#include "../mwgui/messagebox.hpp"
|
||||||
|
|
||||||
namespace MWDialogue
|
namespace MWDialogue
|
||||||
{
|
{
|
||||||
Quest& Journal::getQuest (const std::string& id)
|
Quest& Journal::getQuest (const std::string& id)
|
||||||
|
@ -34,6 +37,10 @@ namespace MWDialogue
|
||||||
Quest& quest = getQuest (id);
|
Quest& quest = getQuest (id);
|
||||||
|
|
||||||
quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here
|
quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here
|
||||||
|
|
||||||
|
std::vector<std::string> empty;
|
||||||
|
std::string notification = "Your Journal has been updated.";
|
||||||
|
mEnvironment.mWindowManager->messageBox (notification, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::setJournalIndex (const std::string& id, int index)
|
void Journal::setJournalIndex (const std::string& id, int index)
|
||||||
|
@ -60,7 +67,12 @@ namespace MWDialogue
|
||||||
|
|
||||||
int Journal::getJournalIndex (const std::string& id) const
|
int Journal::getJournalIndex (const std::string& id) const
|
||||||
{
|
{
|
||||||
return 0;
|
TQuestContainer::const_iterator iter = mQuests.find (id);
|
||||||
|
|
||||||
|
if (iter==mQuests.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return iter->second.getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Journal::TEntryIter Journal::begin() const
|
Journal::TEntryIter Journal::begin() const
|
||||||
|
|
|
@ -139,6 +139,9 @@ namespace MWGui
|
||||||
void Console::disable()
|
void Console::disable()
|
||||||
{
|
{
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
// Remove keyboard focus from the console input whenever the
|
||||||
|
// console is turned off
|
||||||
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::setFont(const std::string &fntName)
|
void Console::setFont(const std::string &fntName)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "window_manager.hpp"
|
#include "window_manager.hpp"
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
#include "components/esm_store/store.hpp"
|
#include "components/esm_store/store.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwdialogue/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -14,32 +16,54 @@
|
||||||
using namespace MWGui;
|
using namespace MWGui;
|
||||||
using namespace Widgets;
|
using namespace Widgets;
|
||||||
|
|
||||||
DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
|
/**
|
||||||
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager)
|
*Copied from the internet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string lower_string(const std::string& str)
|
||||||
|
{
|
||||||
|
std::string lowerCase;
|
||||||
|
|
||||||
|
std::transform (str.begin(), str.end(), std::back_inserter (lowerCase),
|
||||||
|
(int(*)(int)) std::tolower);
|
||||||
|
|
||||||
|
return lowerCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos)
|
||||||
|
{
|
||||||
|
return lower_string(str).find(lower_string(substr),pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment)
|
||||||
|
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager),
|
||||||
|
mEnvironment(environment)
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
center();
|
center();
|
||||||
|
|
||||||
//WindowManager *wm = environment.mWindowManager;
|
//WindowManager *wm = environment.mWindowManager;
|
||||||
setText("NpcName", "Name of character");
|
setText("NpcName", "Name of character");
|
||||||
|
|
||||||
//History view
|
//History view
|
||||||
getWidget(history, "History");
|
getWidget(history, "History");
|
||||||
history->setOverflowToTheLeft(true);
|
history->setOverflowToTheLeft(true);
|
||||||
history->getClient()->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
|
history->getClient()->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onHistoryClicked);
|
||||||
|
history->setMaxTextLength(1000000);
|
||||||
//Topics list
|
//Topics list
|
||||||
getWidget(topicsList, "TopicsList");
|
getWidget(topicsList, "TopicsList");
|
||||||
topicsList->setScrollVisible(true);
|
topicsList->setScrollVisible(true);
|
||||||
topicsList->eventListSelectAccept = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
//topicsList->eventListSelectAccept = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
topicsList->eventListMouseItemActivate = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
topicsList->eventListMouseItemActivate = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
topicsList->eventListChangePosition = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
//topicsList->eventListChangePosition = MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||||
|
|
||||||
MyGUI::ButtonPtr byeButton;
|
MyGUI::ButtonPtr byeButton;
|
||||||
getWidget(byeButton, "ByeButton");
|
getWidget(byeButton, "ByeButton");
|
||||||
byeButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
byeButton->eventMouseButtonClick = MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
||||||
|
|
||||||
updateOptions();
|
getWidget(pDispositionBar, "Disposition");
|
||||||
|
getWidget(pDispositionText,"DispositionText");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
||||||
|
@ -51,70 +75,126 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
||||||
const IntPoint& lastPressed = InputManager::getInstance().getLastLeftPressed();
|
const IntPoint& lastPressed = InputManager::getInstance().getLastLeftPressed();
|
||||||
|
|
||||||
size_t cursorPosition = t->getCursorPosition(lastPressed);
|
size_t cursorPosition = t->getCursorPosition(lastPressed);
|
||||||
if(history->getColorAtPos(cursorPosition) != "#FFFFFF")
|
MyGUI::UString color = history->getColorAtPos(cursorPosition);
|
||||||
|
if(color != "#B29154")
|
||||||
{
|
{
|
||||||
UString key = history->getColorTextAt(cursorPosition);
|
UString key = history->getColorTextAt(cursorPosition);
|
||||||
std::cout << "Clicked on key: " << key << std::endl;
|
if(color == "#686EBA") mEnvironment.mDialogueManager->keywordSelected(lower_string(key));
|
||||||
//eventTopicSelected(key);
|
|
||||||
|
if(color == "#572D21") mEnvironment.mDialogueManager->questionAnswered(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::open()
|
void DialogueWindow::open()
|
||||||
{
|
{
|
||||||
|
topicsList->removeAllItems();
|
||||||
|
pTopicsText.clear();
|
||||||
|
history->eraseText(0,history->getTextLength());
|
||||||
updateOptions();
|
updateOptions();
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
eventBye();
|
mEnvironment.mDialogueManager->goodbyeSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onSelectTopic(MyGUI::List* _sender, size_t _index)
|
void DialogueWindow::onSelectTopic(MyGUI::List* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
return;
|
return;
|
||||||
|
std::string topic = _sender->getItemNameAt(_index);
|
||||||
//const std::string* theTopic = topicsList->getItemDataAt<std::string>(_index);
|
mEnvironment.mDialogueManager->keywordSelected(lower_string(topic));
|
||||||
//std::cout << "Selected: "<< theTopic << std::endl;
|
|
||||||
//eventTopicSelected(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::startDialogue(std::string npcName)
|
||||||
|
{
|
||||||
|
setText("NpcName", npcName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||||
|
{
|
||||||
|
topicsList->removeAllItems();
|
||||||
|
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); it++)
|
||||||
|
{
|
||||||
|
topicsList->addItem(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::removeKeyword(std::string keyWord)
|
||||||
|
{
|
||||||
|
if(topicsList->findItemIndexWith(keyWord) != MyGUI::ITEM_NONE)
|
||||||
|
{
|
||||||
|
topicsList->removeItemAt(topicsList->findItemIndexWith(keyWord));
|
||||||
|
pTopicsText.erase(keyWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2)
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
while((pos = find_str_ci(str,keyword, pos)) != std::string::npos)
|
||||||
|
{
|
||||||
|
if(pos==0)
|
||||||
|
{
|
||||||
|
str.insert(pos,color1);
|
||||||
|
pos += color1.length();
|
||||||
|
pos += keyword.length();
|
||||||
|
str.insert(pos,color2);
|
||||||
|
pos+= color2.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(str.substr(pos -1,1) == " ")
|
||||||
|
{
|
||||||
|
str.insert(pos,color1);
|
||||||
|
pos += color1.length();
|
||||||
|
pos += keyword.length();
|
||||||
|
str.insert(pos,color2);
|
||||||
|
pos+= color2.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos += keyword.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DialogueWindow::parseText(std::string text)
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0;i<topicsList->getItemCount();i++)
|
||||||
|
{
|
||||||
|
std::string keyWord = topicsList->getItemNameAt(i);
|
||||||
|
addColorInString(text,keyWord,"#686EBA","#B29154");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::addText(std::string text)
|
||||||
|
{
|
||||||
|
history->addDialogText("#B29154"+parseText(text)+"#B29154");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::addTitle(std::string text)
|
||||||
|
{
|
||||||
|
history->addDialogHeading(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::askQuestion(std::string question)
|
||||||
|
{
|
||||||
|
history->addDialogText("#572D21"+question+"#B29154"+" ");
|
||||||
|
}
|
||||||
|
|
||||||
void DialogueWindow::updateOptions()
|
void DialogueWindow::updateOptions()
|
||||||
{
|
{
|
||||||
//FIXME Add this properly
|
|
||||||
history->addDialogText("Through the translucent surface of the orb, you see shifting images of distant locations...");
|
|
||||||
for(int z = 0; z < 10; z++)
|
|
||||||
{
|
|
||||||
history->addDialogHeading("Fort Frostmoth");
|
|
||||||
history->addDialogText("The image in the orb flickers, and you see.... The cold courtyard of #FF0000Fort Frostmoth#FFFFFF, battered bu werewolf attack, but still standing, still projecting Imperial might even to this distant and cold corner of the world.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clear the list of topics
|
//Clear the list of topics
|
||||||
topicsList->removeAllItems();
|
topicsList->removeAllItems();
|
||||||
int i = 0;
|
pTopicsText.clear();
|
||||||
topicsList->addItem("Ald'ruhn", i++);
|
history->eraseText(0,history->getTextLength());
|
||||||
topicsList->addItem("Balmora", i++);
|
|
||||||
topicsList->addItem("Sadrith Mora", i++);
|
|
||||||
topicsList->addItem("Vivec", i++);
|
|
||||||
topicsList->addItem("Ald Velothi", i++);
|
|
||||||
topicsList->addItem("Caldera", i++);
|
|
||||||
topicsList->addItem("Dagon Fel ", i++);
|
|
||||||
topicsList->addItem("Gnaar Mok", i++);
|
|
||||||
topicsList->addItem("Gnisis", i++);
|
|
||||||
topicsList->addItem("Hla Oad", i++);
|
|
||||||
topicsList->addItem("Khuul", i++);
|
|
||||||
topicsList->addItem("Maar Gan", i++);
|
|
||||||
topicsList->addItem("Molag Mar", i++);
|
|
||||||
topicsList->addItem("Pelagiad", i++);
|
|
||||||
topicsList->addItem("Seyda Neen", i++);
|
|
||||||
topicsList->addItem("Suran", i++);
|
|
||||||
topicsList->addItem("Tel Aruhn", i++);
|
|
||||||
topicsList->addItem("Tel Branora", i++);
|
|
||||||
topicsList->addItem("Tel Fyr", i++);
|
|
||||||
topicsList->addItem("Tel Mora", i++);
|
|
||||||
topicsList->addItem("Tel Vos", i++);
|
|
||||||
topicsList->addItem("Vos", i++);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pDispositionBar->setProgressRange(100);
|
||||||
|
pDispositionBar->setProgressPosition(40);
|
||||||
|
pDispositionText->eraseText(0,pDispositionText->getTextLength());
|
||||||
|
pDispositionText->addText("#B29154"+std::string("40/100")+"#B29154");
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@ namespace MWGui
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Environment;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file contains the dialouge window
|
This file contains the dialouge window
|
||||||
Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml.
|
Layout is defined by resources/mygui/openmw_dialogue_window_layout.xml.
|
||||||
|
@ -23,7 +28,7 @@ namespace MWGui
|
||||||
class DialogueWindow: public WindowBase
|
class DialogueWindow: public WindowBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DialogueWindow(WindowManager& parWindowManager);
|
DialogueWindow(WindowManager& parWindowManager,MWWorld::Environment& environment);
|
||||||
|
|
||||||
void open();
|
void open();
|
||||||
|
|
||||||
|
@ -35,6 +40,14 @@ namespace MWGui
|
||||||
*/
|
*/
|
||||||
EventHandle_Void eventBye;
|
EventHandle_Void eventBye;
|
||||||
|
|
||||||
|
void startDialogue(std::string npcName);
|
||||||
|
void stopDialogue();
|
||||||
|
void setKeywords(std::list<std::string> keyWord);
|
||||||
|
void removeKeyword(std::string keyWord);
|
||||||
|
void addText(std::string text);
|
||||||
|
void addTitle(std::string text);
|
||||||
|
void askQuestion(std::string question);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectTopic(MyGUI::List* _sender, size_t _index);
|
void onSelectTopic(MyGUI::List* _sender, size_t _index);
|
||||||
void onByeClicked(MyGUI::Widget* _sender);
|
void onByeClicked(MyGUI::Widget* _sender);
|
||||||
|
@ -42,9 +55,18 @@ namespace MWGui
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateOptions();
|
void updateOptions();
|
||||||
|
/**
|
||||||
|
*Helper function that add topic keyword in blue in a text.
|
||||||
|
*/
|
||||||
|
std::string parseText(std::string text);
|
||||||
|
|
||||||
DialogeHistory* history;
|
DialogeHistory* history;
|
||||||
MyGUI::ListPtr topicsList;
|
MyGUI::ListPtr topicsList;
|
||||||
|
MyGUI::ProgressPtr pDispositionBar;
|
||||||
|
MyGUI::EditPtr pDispositionText;
|
||||||
|
std::map<std::string,std::string> pTopicsText;// this map links keyword and "real" text.
|
||||||
|
|
||||||
|
MWWorld::Environment& mEnvironment;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,9 +61,9 @@ UString DialogeHistory::getColorTextAt(size_t _pos)
|
||||||
|
|
||||||
void DialogeHistory::addDialogHeading(const UString& parText)
|
void DialogeHistory::addDialogHeading(const UString& parText)
|
||||||
{
|
{
|
||||||
UString head("\n#00FF00");
|
UString head("\n#D8C09A");
|
||||||
head.append(parText);
|
head.append(parText);
|
||||||
head.append("#FFFFFF\n");
|
head.append("#B29154\n");
|
||||||
addText(head);
|
addText(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
if(it->current >= it->max)
|
if(it->current >= it->max)
|
||||||
{
|
{
|
||||||
it->messageBox->mMarkedToDelete = true;
|
it->messageBox->mMarkedToDelete = true;
|
||||||
|
|
||||||
if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one
|
if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one
|
||||||
{
|
{
|
||||||
// collect all with mMarkedToDelete and delete them.
|
// collect all with mMarkedToDelete and delete them.
|
||||||
|
@ -47,7 +47,7 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
|
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
|
||||||
delete mInterMessageBoxe;
|
delete mInterMessageBoxe;
|
||||||
mInterMessageBoxe = NULL;
|
mInterMessageBoxe = NULL;
|
||||||
|
@ -57,20 +57,18 @@ void MessageBoxManager::onFrame (float frameDuration)
|
||||||
|
|
||||||
void MessageBoxManager::createMessageBox (const std::string& message)
|
void MessageBoxManager::createMessageBox (const std::string& message)
|
||||||
{
|
{
|
||||||
std::cout << "MessageBox: " << message << std::endl;
|
|
||||||
|
|
||||||
MessageBox *box = new MessageBox(*this, message);
|
MessageBox *box = new MessageBox(*this, message);
|
||||||
|
|
||||||
removeMessageBox(message.length()*mMessageBoxSpeed, box);
|
removeMessageBox(message.length()*mMessageBoxSpeed, box);
|
||||||
|
|
||||||
mMessageBoxes.push_back(box);
|
mMessageBoxes.push_back(box);
|
||||||
std::vector<MessageBox*>::iterator it;
|
std::vector<MessageBox*>::iterator it;
|
||||||
|
|
||||||
if(mMessageBoxes.size() > 3) {
|
if(mMessageBoxes.size() > 3) {
|
||||||
delete *mMessageBoxes.begin();
|
delete *mMessageBoxes.begin();
|
||||||
mMessageBoxes.erase(mMessageBoxes.begin());
|
mMessageBoxes.erase(mMessageBoxes.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
int height = 0;
|
int height = 0;
|
||||||
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
|
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -88,9 +86,9 @@ bool MessageBoxManager::createInteractiveMessageBox (const std::string& message,
|
||||||
std::cout << "interactive MessageBox: " << message << " - ";
|
std::cout << "interactive MessageBox: " << message << " - ";
|
||||||
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
|
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
|
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +103,7 @@ void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox)
|
||||||
timer.current = 0;
|
timer.current = 0;
|
||||||
timer.max = time;
|
timer.max = time;
|
||||||
timer.messageBox = msgbox;
|
timer.messageBox = msgbox;
|
||||||
|
|
||||||
mTimers.insert(mTimers.end(), timer);
|
mTimers.insert(mTimers.end(), timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,25 +150,25 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin
|
||||||
mBottomPadding = 20;
|
mBottomPadding = 20;
|
||||||
mNextBoxPadding = 20;
|
mNextBoxPadding = 20;
|
||||||
mMarkedToDelete = false;
|
mMarkedToDelete = false;
|
||||||
|
|
||||||
getWidget(mMessageWidget, "message");
|
getWidget(mMessageWidget, "message");
|
||||||
|
|
||||||
mMessageWidget->setOverflowToTheLeft(true);
|
mMessageWidget->setOverflowToTheLeft(true);
|
||||||
mMessageWidget->addText(cMessage);
|
mMessageWidget->addText(cMessage);
|
||||||
|
|
||||||
MyGUI::IntSize size;
|
MyGUI::IntSize size;
|
||||||
size.width = mFixedWidth;
|
size.width = mFixedWidth;
|
||||||
size.height = 100; // dummy
|
size.height = 100; // dummy
|
||||||
|
|
||||||
MyGUI::IntCoord coord;
|
MyGUI::IntCoord coord;
|
||||||
coord.left = 10; // dummy
|
coord.left = 10; // dummy
|
||||||
coord.top = 10; // dummy
|
coord.top = 10; // dummy
|
||||||
|
|
||||||
mMessageWidget->setSize(size);
|
mMessageWidget->setSize(size);
|
||||||
|
|
||||||
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
||||||
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
|
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
|
||||||
|
|
||||||
mMainWidget->setSize(size);
|
mMainWidget->setSize(size);
|
||||||
size.width -= 15; // this is to center the text (see messagebox_layout.xml, Widget type="Edit" position="-2 -3 0 0")
|
size.width -= 15; // this is to center the text (see messagebox_layout.xml, Widget type="Edit" position="-2 -3 0 0")
|
||||||
mMessageWidget->setSize(size);
|
mMessageWidget->setSize(size);
|
||||||
|
@ -182,11 +180,11 @@ void MessageBox::update (int height)
|
||||||
MyGUI::IntCoord coord;
|
MyGUI::IntCoord coord;
|
||||||
coord.left = (gameWindowSize.width - mFixedWidth)/2;
|
coord.left = (gameWindowSize.width - mFixedWidth)/2;
|
||||||
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
|
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
|
||||||
|
|
||||||
MyGUI::IntSize size;
|
MyGUI::IntSize size;
|
||||||
size.width = mFixedWidth;
|
size.width = mFixedWidth;
|
||||||
size.height = mHeight;
|
size.height = mHeight;
|
||||||
|
|
||||||
mMainWidget->setCoord(coord);
|
mMainWidget->setCoord(coord);
|
||||||
mMainWidget->setSize(size);
|
mMainWidget->setSize(size);
|
||||||
mMainWidget->setVisible(true);
|
mMainWidget->setVisible(true);
|
||||||
|
@ -211,26 +209,26 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
int buttonTopPadding = 5; // ^-- if vertical
|
int buttonTopPadding = 5; // ^-- if vertical
|
||||||
int buttonPadding = 5; // padding between button label and button itself
|
int buttonPadding = 5; // padding between button label and button itself
|
||||||
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
|
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
|
||||||
|
|
||||||
mMarkedToDelete = false;
|
mMarkedToDelete = false;
|
||||||
|
|
||||||
|
|
||||||
getWidget(mMessageWidget, "message");
|
getWidget(mMessageWidget, "message");
|
||||||
getWidget(mButtonsWidget, "buttons");
|
getWidget(mButtonsWidget, "buttons");
|
||||||
|
|
||||||
mMessageWidget->setOverflowToTheLeft(true);
|
mMessageWidget->setOverflowToTheLeft(true);
|
||||||
mMessageWidget->addText(message);
|
mMessageWidget->addText(message);
|
||||||
|
|
||||||
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
|
||||||
|
|
||||||
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
|
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
|
||||||
|
|
||||||
int biggestButtonWidth = 0;
|
int biggestButtonWidth = 0;
|
||||||
int buttonWidth = 0;
|
int buttonWidth = 0;
|
||||||
int buttonsWidth = 0;
|
int buttonsWidth = 0;
|
||||||
int buttonHeight = 0;
|
int buttonHeight = 0;
|
||||||
MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
|
MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
|
||||||
|
|
||||||
std::vector<std::string>::const_iterator it;
|
std::vector<std::string>::const_iterator it;
|
||||||
for(it = buttons.begin(); it != buttons.end(); ++it)
|
for(it = buttons.begin(); it != buttons.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -240,28 +238,28 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
dummyCoord,
|
dummyCoord,
|
||||||
MyGUI::Align::Default);
|
MyGUI::Align::Default);
|
||||||
button->setCaption(*it);
|
button->setCaption(*it);
|
||||||
|
|
||||||
button->eventMouseButtonClick = MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed);
|
button->eventMouseButtonClick = MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed);
|
||||||
|
|
||||||
mButtons.push_back(button);
|
mButtons.push_back(button);
|
||||||
|
|
||||||
buttonWidth = button->_getTextSize().width + 2*buttonPadding + buttonLeftPadding;
|
buttonWidth = button->_getTextSize().width + 2*buttonPadding + buttonLeftPadding;
|
||||||
buttonsWidth += buttonWidth;
|
buttonsWidth += buttonWidth;
|
||||||
buttonHeight = button->_getTextSize().height + 2*buttonPadding + buttonTopPadding;
|
buttonHeight = button->_getTextSize().height + 2*buttonPadding + buttonTopPadding;
|
||||||
|
|
||||||
if(buttonWidth > biggestButtonWidth)
|
if(buttonWidth > biggestButtonWidth)
|
||||||
{
|
{
|
||||||
biggestButtonWidth = buttonWidth;
|
biggestButtonWidth = buttonWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buttonsWidth += buttonLeftPadding;
|
buttonsWidth += buttonLeftPadding;
|
||||||
|
|
||||||
MyGUI::IntSize mainWidgetSize;
|
MyGUI::IntSize mainWidgetSize;
|
||||||
if(buttonsWidth < fixedWidth)
|
if(buttonsWidth < fixedWidth)
|
||||||
{
|
{
|
||||||
// on one line
|
// on one line
|
||||||
std::cout << "on one line" << std::endl;
|
std::cout << "on one line" << std::endl;
|
||||||
|
|
||||||
if(textSize.width + 2*textPadding < buttonsWidth)
|
if(textSize.width + 2*textPadding < buttonsWidth)
|
||||||
{
|
{
|
||||||
std::cout << "width = buttonsWidth" << std::endl;
|
std::cout << "width = buttonsWidth" << std::endl;
|
||||||
|
@ -272,48 +270,48 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
mainWidgetSize.width = textSize.width + 3*textPadding;
|
mainWidgetSize.width = textSize.width + 3*textPadding;
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
MyGUI::IntCoord absCoord;
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
||||||
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
|
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
mMainWidget->setCoord(absCoord);
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
||||||
messageWidgetCoord.top = textPadding;
|
messageWidgetCoord.top = textPadding;
|
||||||
mMessageWidget->setCoord(messageWidgetCoord);
|
mMessageWidget->setCoord(messageWidgetCoord);
|
||||||
|
|
||||||
mMessageWidget->setSize(textSize);
|
mMessageWidget->setSize(textSize);
|
||||||
|
|
||||||
MyGUI::IntCoord buttonCord;
|
MyGUI::IntCoord buttonCord;
|
||||||
MyGUI::IntSize buttonSize(0, buttonHeight);
|
MyGUI::IntSize buttonSize(0, buttonHeight);
|
||||||
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
|
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
|
||||||
|
|
||||||
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
||||||
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
||||||
{
|
{
|
||||||
buttonCord.left = left;
|
buttonCord.left = left;
|
||||||
buttonCord.top = textSize.height + textButtonPadding;
|
buttonCord.top = textSize.height + textButtonPadding;
|
||||||
|
|
||||||
buttonSize.width = (*button)->_getTextSize().width + 2*buttonPadding;
|
buttonSize.width = (*button)->_getTextSize().width + 2*buttonPadding;
|
||||||
buttonSize.height = (*button)->_getTextSize().height + 2*buttonPadding;
|
buttonSize.height = (*button)->_getTextSize().height + 2*buttonPadding;
|
||||||
|
|
||||||
(*button)->setCoord(buttonCord);
|
(*button)->setCoord(buttonCord);
|
||||||
(*button)->setSize(buttonSize);
|
(*button)->setSize(buttonSize);
|
||||||
|
|
||||||
left += buttonSize.width + buttonLeftPadding;
|
left += buttonSize.width + buttonLeftPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// among each other
|
// among each other
|
||||||
|
|
||||||
if(biggestButtonWidth > textSize.width) {
|
if(biggestButtonWidth > textSize.width) {
|
||||||
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
|
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
|
||||||
}
|
}
|
||||||
|
@ -321,46 +319,46 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
|
||||||
mainWidgetSize.width = textSize.width + 3*textPadding;
|
mainWidgetSize.width = textSize.width + 3*textPadding;
|
||||||
}
|
}
|
||||||
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
|
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
|
||||||
|
|
||||||
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
|
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
|
||||||
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
MyGUI::IntCoord absCoord;
|
MyGUI::IntCoord absCoord;
|
||||||
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
|
||||||
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
|
||||||
|
|
||||||
mMainWidget->setCoord(absCoord);
|
mMainWidget->setCoord(absCoord);
|
||||||
mMainWidget->setSize(mainWidgetSize);
|
mMainWidget->setSize(mainWidgetSize);
|
||||||
|
|
||||||
|
|
||||||
MyGUI::IntCoord messageWidgetCoord;
|
MyGUI::IntCoord messageWidgetCoord;
|
||||||
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
|
||||||
messageWidgetCoord.top = textPadding;
|
messageWidgetCoord.top = textPadding;
|
||||||
mMessageWidget->setCoord(messageWidgetCoord);
|
mMessageWidget->setCoord(messageWidgetCoord);
|
||||||
|
|
||||||
mMessageWidget->setSize(textSize);
|
mMessageWidget->setSize(textSize);
|
||||||
|
|
||||||
MyGUI::IntCoord buttonCord;
|
MyGUI::IntCoord buttonCord;
|
||||||
MyGUI::IntSize buttonSize(0, buttonHeight);
|
MyGUI::IntSize buttonSize(0, buttonHeight);
|
||||||
|
|
||||||
int top = textButtonPadding + buttonTopPadding + textSize.height;
|
int top = textButtonPadding + buttonTopPadding + textSize.height;
|
||||||
|
|
||||||
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
std::vector<MyGUI::ButtonPtr>::const_iterator button;
|
||||||
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
for(button = mButtons.begin(); button != mButtons.end(); ++button)
|
||||||
{
|
{
|
||||||
buttonSize.width = (*button)->_getTextSize().width + buttonPadding*2;
|
buttonSize.width = (*button)->_getTextSize().width + buttonPadding*2;
|
||||||
buttonSize.height = (*button)->_getTextSize().height + buttonPadding*2;
|
buttonSize.height = (*button)->_getTextSize().height + buttonPadding*2;
|
||||||
|
|
||||||
buttonCord.top = top;
|
buttonCord.top = top;
|
||||||
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
|
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
|
||||||
|
|
||||||
(*button)->setCoord(buttonCord);
|
(*button)->setCoord(buttonCord);
|
||||||
(*button)->setSize(buttonSize);
|
(*button)->setSize(buttonSize);
|
||||||
|
|
||||||
top += buttonSize.height + 2*buttonTopPadding;
|
top += buttonSize.height + 2*buttonTopPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,8 +385,3 @@ int InteractiveMessageBox::readPressedButton ()
|
||||||
mButtonPressed = -1;
|
mButtonPressed = -1;
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ WindowManager::WindowManager(MWWorld::Environment& environment,
|
||||||
console = new Console(w,h, environment, extensions);
|
console = new Console(w,h, environment, extensions);
|
||||||
mJournal = new JournalWindow(*this);
|
mJournal = new JournalWindow(*this);
|
||||||
mMessageBoxManager = new MessageBoxManager(this);
|
mMessageBoxManager = new MessageBoxManager(this);
|
||||||
|
dialogueWindow = new DialogueWindow(*this,environment);
|
||||||
|
|
||||||
// The HUD is always on
|
// The HUD is always on
|
||||||
hud->setVisible(true);
|
hud->setVisible(true);
|
||||||
|
@ -149,6 +150,7 @@ void WindowManager::updateVisible()
|
||||||
stats->setVisible(false);
|
stats->setVisible(false);
|
||||||
console->disable();
|
console->disable();
|
||||||
mJournal->setVisible(false);
|
mJournal->setVisible(false);
|
||||||
|
dialogueWindow->setVisible(false);
|
||||||
|
|
||||||
// Mouse is visible whenever we're not in game mode
|
// Mouse is visible whenever we're not in game mode
|
||||||
gui->setVisiblePointer(isGuiMode());
|
gui->setVisiblePointer(isGuiMode());
|
||||||
|
@ -195,11 +197,6 @@ void WindowManager::updateVisible()
|
||||||
|
|
||||||
if (mode == GM_Dialogue)
|
if (mode == GM_Dialogue)
|
||||||
{
|
{
|
||||||
if (!dialogueWindow)
|
|
||||||
{
|
|
||||||
dialogueWindow = new DialogueWindow(*this);
|
|
||||||
dialogueWindow->eventBye = MyGUI::newDelegate(this, &WindowManager::onDialogueWindowBye);
|
|
||||||
}
|
|
||||||
dialogueWindow->open();
|
dialogueWindow->open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -349,6 +346,7 @@ void WindowManager::updateSkillArea()
|
||||||
|
|
||||||
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
|
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
|
||||||
{
|
{
|
||||||
|
std::cout << "dialogue a la poubelle";
|
||||||
assert(dialog);
|
assert(dialog);
|
||||||
if (!dialog)
|
if (!dialog)
|
||||||
return;
|
return;
|
||||||
|
@ -387,7 +385,8 @@ void WindowManager::onDialogueWindowBye()
|
||||||
if (dialogueWindow)
|
if (dialogueWindow)
|
||||||
{
|
{
|
||||||
//FIXME set some state and stuff?
|
//FIXME set some state and stuff?
|
||||||
removeDialog(dialogueWindow);
|
//removeDialog(dialogueWindow);
|
||||||
|
dialogueWindow->setVisible(false);
|
||||||
}
|
}
|
||||||
setGuiMode(GM_Game);
|
setGuiMode(GM_Game);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,8 @@ namespace MWGui
|
||||||
updateVisible();
|
updateVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWGui::DialogueWindow* getDialogueWindow() {return dialogueWindow;}
|
||||||
|
|
||||||
MyGUI::Gui* getGui() const { return gui; }
|
MyGUI::Gui* getGui() const { return gui; }
|
||||||
|
|
||||||
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)
|
void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount)
|
||||||
|
|
|
@ -51,7 +51,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||||
|
|
||||||
//mSkyManager = 0;
|
//mSkyManager = 0;
|
||||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
|
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||||
|
|
||||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||||
mSun = 0;
|
mSun = 0;
|
||||||
|
|
|
@ -10,16 +10,12 @@
|
||||||
|
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
// the speed at which the clouds are animated
|
|
||||||
#define CLOUD_SPEED 0.001
|
|
||||||
|
|
||||||
// this distance has to be set accordingly so that the
|
|
||||||
// celestial bodies are behind the clouds, but in front of the atmosphere
|
|
||||||
#define CELESTIAL_BODY_DISTANCE 1000.f
|
|
||||||
|
|
||||||
BillboardObject::BillboardObject( const String& textureName,
|
BillboardObject::BillboardObject( const String& textureName,
|
||||||
const float initialSize,
|
const float initialSize,
|
||||||
const Vector3& position,
|
const Vector3& position,
|
||||||
|
@ -50,7 +46,7 @@ void BillboardObject::setVisibility(const float visibility)
|
||||||
void BillboardObject::setPosition(const Vector3& pPosition)
|
void BillboardObject::setPosition(const Vector3& pPosition)
|
||||||
{
|
{
|
||||||
Vector3 normalised = pPosition.normalisedCopy();
|
Vector3 normalised = pPosition.normalisedCopy();
|
||||||
Vector3 finalPosition = normalised * CELESTIAL_BODY_DISTANCE;
|
Vector3 finalPosition = normalised * 1000.f;
|
||||||
|
|
||||||
mBBSet->setCommonDirection( -normalised );
|
mBBSet->setCommonDirection( -normalised );
|
||||||
|
|
||||||
|
@ -85,7 +81,7 @@ void BillboardObject::init(const String& textureName,
|
||||||
{
|
{
|
||||||
SceneManager* sceneMgr = rootNode->getCreator();
|
SceneManager* sceneMgr = rootNode->getCreator();
|
||||||
|
|
||||||
Vector3 finalPosition = position.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
Vector3 finalPosition = position.normalisedCopy() * 1000.f;
|
||||||
|
|
||||||
static unsigned int bodyCount=0;
|
static unsigned int bodyCount=0;
|
||||||
|
|
||||||
|
@ -296,9 +292,10 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
|
||||||
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env) :
|
||||||
mGlareFade(0), mGlareEnabled(false)
|
mGlareFade(0), mGlareEnabled(false)
|
||||||
{
|
{
|
||||||
|
mEnvironment = env;
|
||||||
mViewport = pCamera->getViewport();
|
mViewport = pCamera->getViewport();
|
||||||
mSceneMgr = pMwRoot->getCreator();
|
mSceneMgr = pMwRoot->getCreator();
|
||||||
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode();
|
||||||
|
@ -312,7 +309,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
Pass* pass = material->getTechnique(0)->getPass(0);
|
Pass* pass = material->getTechnique(0)->getPass(0);
|
||||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
mThunderTextureUnit = pass->createTextureUnitState();
|
mThunderTextureUnit = pass->createTextureUnitState();
|
||||||
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); // always black colour
|
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f));
|
||||||
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
|
||||||
OverlayManager& ovm = OverlayManager::getSingleton();
|
OverlayManager& ovm = OverlayManager::getSingleton();
|
||||||
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
mThunderOverlay = ovm.create( "ThunderOverlay" );
|
||||||
|
@ -504,7 +501,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) :
|
||||||
" uniform float4 emissive \n"
|
" uniform float4 emissive \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" uv += float2(1,1) * time * speed * "<<CLOUD_SPEED<<"; \n" // Scroll in x,y direction
|
" uv += float2(1,0) * time * speed * 0.003; \n" // Scroll in x direction
|
||||||
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||||
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"
|
||||||
"}";
|
"}";
|
||||||
|
@ -558,7 +555,7 @@ void SkyManager::update(float duration)
|
||||||
if (!mEnabled) return;
|
if (!mEnabled) return;
|
||||||
|
|
||||||
// UV Scroll the clouds
|
// UV Scroll the clouds
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1);
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", mEnvironment->mWorld->getTimeScaleFactor()/30.f);
|
||||||
|
|
||||||
/// \todo improve this
|
/// \todo improve this
|
||||||
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
|
@ -594,8 +591,8 @@ void SkyManager::update(float duration)
|
||||||
mMasser->setVisible(mMasserEnabled);
|
mMasser->setVisible(mMasserEnabled);
|
||||||
mSecunda->setVisible(mSecundaEnabled);
|
mSecunda->setVisible(mSecundaEnabled);
|
||||||
|
|
||||||
// rotate the whole sky by 360 degrees every 4 days
|
// rotate the stars by 360 degrees every 4 days
|
||||||
mRootNode->roll(Degree(mHourDiff*360/96.f));
|
mAtmosphereNight->roll(Degree(mEnvironment->mWorld->getTimeScaleFactor()*duration*360 / (3600*96.f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::enable()
|
void SkyManager::enable()
|
||||||
|
@ -692,6 +689,7 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
strength = 1.f;
|
strength = 1.f;
|
||||||
|
|
||||||
mSunGlare->setVisibility(weather.mGlareView * strength);
|
mSunGlare->setVisibility(weather.mGlareView * strength);
|
||||||
|
mSun->setVisibility(strength);
|
||||||
|
|
||||||
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||||
}
|
}
|
||||||
|
@ -775,9 +773,6 @@ void SkyManager::setSecundaFade(const float fade)
|
||||||
|
|
||||||
void SkyManager::setHour(double hour)
|
void SkyManager::setHour(double hour)
|
||||||
{
|
{
|
||||||
mHourDiff = mHour - hour;
|
|
||||||
if (mHourDiff > 0) mHourDiff -= 24;
|
|
||||||
|
|
||||||
mHour = hour;
|
mHour = hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace MWRender
|
||||||
class SkyManager
|
class SkyManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera);
|
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env);
|
||||||
~SkyManager();
|
~SkyManager();
|
||||||
|
|
||||||
void update(float duration);
|
void update(float duration);
|
||||||
|
@ -164,12 +164,11 @@ namespace MWRender
|
||||||
Ogre::Vector3 getRealSunPos();
|
Ogre::Vector3 getRealSunPos();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MWWorld::Environment* mEnvironment;
|
||||||
float mHour;
|
float mHour;
|
||||||
int mDay;
|
int mDay;
|
||||||
int mMonth;
|
int mMonth;
|
||||||
|
|
||||||
float mHourDiff;
|
|
||||||
|
|
||||||
BillboardObject* mSun;
|
BillboardObject* mSun;
|
||||||
BillboardObject* mSunGlare;
|
BillboardObject* mSunGlare;
|
||||||
Moon* mMasser;
|
Moon* mMasser;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <components/interpreter/opcodes.hpp>
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
#include "../mwdialogue/journal.hpp"
|
#include "../mwdialogue/journal.hpp"
|
||||||
|
#include "../mwdialogue/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
|
|
||||||
|
@ -72,15 +73,62 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpAddTopic : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext& context
|
||||||
|
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
|
std::string topic = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
context.getEnvironment().mDialogueManager->addTopic(topic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpChoice : public Interpreter::Opcode1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||||
|
{
|
||||||
|
MWScript::InterpreterContext& context
|
||||||
|
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||||
|
MWDialogue::DialogueManager* dialogue = context.getEnvironment().mDialogueManager;
|
||||||
|
while(arg0>0)
|
||||||
|
{
|
||||||
|
std::string question = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
arg0 = arg0 -1;
|
||||||
|
Interpreter::Type_Integer choice = 1;
|
||||||
|
if(arg0>0)
|
||||||
|
{
|
||||||
|
choice = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
arg0 = arg0 -1;
|
||||||
|
}
|
||||||
|
dialogue->askQuestion(question,choice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const int opcodeJournal = 0x2000133;
|
const int opcodeJournal = 0x2000133;
|
||||||
const int opcodeSetJournalIndex = 0x2000134;
|
const int opcodeSetJournalIndex = 0x2000134;
|
||||||
const int opcodeGetJournalIndex = 0x2000135;
|
const int opcodeGetJournalIndex = 0x2000135;
|
||||||
|
const int opcodeAddTopic = 0x200013a;
|
||||||
|
const int opcodeChoice = 0x2000a;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
extensions.registerInstruction ("journal", "cl", opcodeJournal);
|
extensions.registerInstruction ("journal", "cl", opcodeJournal);
|
||||||
extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex);
|
extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex);
|
||||||
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
|
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
|
||||||
|
extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic);
|
||||||
|
extensions.registerInstruction ("choice", "/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -88,6 +136,8 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (opcodeJournal, new OpJournal);
|
interpreter.installSegment5 (opcodeJournal, new OpJournal);
|
||||||
interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex);
|
interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex);
|
||||||
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
|
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
|
||||||
|
interpreter.installSegment5 (opcodeAddTopic, new OpAddTopic);
|
||||||
|
interpreter.installSegment3 (opcodeChoice,new OpChoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ op 0x20006: PlayAnim
|
||||||
op 0x20007: PlayAnim, explicit reference
|
op 0x20007: PlayAnim, explicit reference
|
||||||
op 0x20008: LoopAnim
|
op 0x20008: LoopAnim
|
||||||
op 0x20009: LoopAnim, explicit reference
|
op 0x20009: LoopAnim, explicit reference
|
||||||
opcodes 0x2000a-0x3ffff unused
|
op 0x2000a: Choice
|
||||||
|
opcodes 0x2000b-0x3ffff unused
|
||||||
|
|
||||||
Segment 4:
|
Segment 4:
|
||||||
(not implemented yet)
|
(not implemented yet)
|
||||||
|
@ -115,6 +116,7 @@ op 0x2000136: GetPCCell
|
||||||
op 0x2000137: GetButtonPressed
|
op 0x2000137: GetButtonPressed
|
||||||
op 0x2000138: SkipAnim
|
op 0x2000138: SkipAnim
|
||||||
op 0x2000139: SkipAnim, expplicit reference
|
op 0x2000139: SkipAnim, expplicit reference
|
||||||
|
op 0x200013a: AddTopic
|
||||||
op 0x200013b: twf
|
op 0x200013b: twf
|
||||||
op 0x200013c: FadeIn
|
op 0x200013c: FadeIn
|
||||||
op 0x200013d: FadeOut
|
op 0x200013d: FadeOut
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
std::vector<Interpreter::Type_Code> code;
|
std::vector<Interpreter::Type_Code> code;
|
||||||
mParser.getCode (code);
|
mParser.getCode (code);
|
||||||
mScripts.insert (std::make_pair (name, code));
|
mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals())));
|
||||||
|
|
||||||
// TODO sanity check on generated locals
|
// TODO sanity check on generated locals
|
||||||
|
|
||||||
|
@ -77,8 +77,7 @@ namespace MWScript
|
||||||
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
void ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext)
|
||||||
{
|
{
|
||||||
// compile script
|
// compile script
|
||||||
std::map<std::string, std::vector<Interpreter::Type_Code> >::iterator iter =
|
ScriptCollection::iterator iter = mScripts.find (name);
|
||||||
mScripts.find (name);
|
|
||||||
|
|
||||||
if (iter==mScripts.end())
|
if (iter==mScripts.end())
|
||||||
{
|
{
|
||||||
|
@ -86,7 +85,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
// failed -> ignore script from now on.
|
// failed -> ignore script from now on.
|
||||||
std::vector<Interpreter::Type_Code> empty;
|
std::vector<Interpreter::Type_Code> empty;
|
||||||
mScripts.insert (std::make_pair (name, empty));
|
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +94,7 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute script
|
// execute script
|
||||||
if (!iter->second.empty())
|
if (!iter->second.first.empty())
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!mOpcodesInstalled)
|
if (!mOpcodesInstalled)
|
||||||
|
@ -104,7 +103,7 @@ namespace MWScript
|
||||||
mOpcodesInstalled = true;
|
mOpcodesInstalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mInterpreter.run (&iter->second[0], iter->second.size(), interpreterContext);
|
mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +112,7 @@ namespace MWScript
|
||||||
if (mVerbose)
|
if (mVerbose)
|
||||||
std::cerr << "(" << e.what() << ")" << std::endl;
|
std::cerr << "(" << e.what() << ")" << std::endl;
|
||||||
|
|
||||||
iter->second.clear(); // don't execute again.
|
iter->second.first.clear(); // don't execute again.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,4 +131,24 @@ namespace MWScript
|
||||||
|
|
||||||
return std::make_pair (count, success);
|
return std::make_pair (count, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Compiler::Locals& ScriptManager::getLocals (const std::string& name)
|
||||||
|
{
|
||||||
|
ScriptCollection::iterator iter = mScripts.find (name);
|
||||||
|
|
||||||
|
if (iter==mScripts.end())
|
||||||
|
{
|
||||||
|
if (!compile (name))
|
||||||
|
{
|
||||||
|
// failed -> ignore script from now on.
|
||||||
|
std::vector<Interpreter::Type_Code> empty;
|
||||||
|
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||||
|
throw std::runtime_error ("failed to compile script " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = mScripts.find (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter->second.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,11 @@ namespace MWScript
|
||||||
Interpreter::Interpreter mInterpreter;
|
Interpreter::Interpreter mInterpreter;
|
||||||
bool mOpcodesInstalled;
|
bool mOpcodesInstalled;
|
||||||
|
|
||||||
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts;
|
typedef std::pair<std::vector<Interpreter::Type_Code>, Compiler::Locals> CompiledScript;
|
||||||
|
typedef std::map<std::string, CompiledScript> ScriptCollection;
|
||||||
|
|
||||||
|
|
||||||
|
ScriptCollection mScripts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -56,6 +60,9 @@ namespace MWScript
|
||||||
std::pair<int, int> compileAll();
|
std::pair<int, int> compileAll();
|
||||||
///< Compile all scripts
|
///< Compile all scripts
|
||||||
/// \return count, success
|
/// \return count, success
|
||||||
|
|
||||||
|
Compiler::Locals& getLocals (const std::string& name);
|
||||||
|
///< Return locals for script \a name.
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace MWSound
|
||||||
, updater(mgr)
|
, updater(mgr)
|
||||||
, cameraTracker(mgr)
|
, cameraTracker(mgr)
|
||||||
, mCurrentPlaylist(NULL)
|
, mCurrentPlaylist(NULL)
|
||||||
|
, mUsingSound(useSound)
|
||||||
{
|
{
|
||||||
if(useSound)
|
if(useSound)
|
||||||
{
|
{
|
||||||
|
@ -105,8 +106,11 @@ namespace MWSound
|
||||||
|
|
||||||
SoundManager::~SoundManager()
|
SoundManager::~SoundManager()
|
||||||
{
|
{
|
||||||
Ogre::Root::getSingleton().removeFrameListener(&updater);
|
if(mUsingSound)
|
||||||
cameraTracker.unfollowCamera();
|
{
|
||||||
|
Ogre::Root::getSingleton().removeFrameListener(&updater);
|
||||||
|
cameraTracker.unfollowCamera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a soundId to file name, and modify the volume
|
// Convert a soundId to file name, and modify the volume
|
||||||
|
@ -354,6 +358,9 @@ namespace MWSound
|
||||||
|
|
||||||
void SoundManager::playPlaylist(std::string playlist)
|
void SoundManager::playPlaylist(std::string playlist)
|
||||||
{
|
{
|
||||||
|
if (!mUsingSound)
|
||||||
|
return;
|
||||||
|
|
||||||
if (playlist == "")
|
if (playlist == "")
|
||||||
{
|
{
|
||||||
if(!isMusicPlaying())
|
if(!isMusicPlaying())
|
||||||
|
@ -375,6 +382,9 @@ namespace MWSound
|
||||||
|
|
||||||
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
|
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
|
||||||
{
|
{
|
||||||
|
if (!mUsingSound)
|
||||||
|
return;
|
||||||
|
|
||||||
// The range values are not tested
|
// The range values are not tested
|
||||||
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true);
|
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true);
|
||||||
if(!filePath.empty())
|
if(!filePath.empty())
|
||||||
|
|
|
@ -82,6 +82,8 @@ namespace MWSound
|
||||||
|
|
||||||
IDMap mLoopedSounds;
|
IDMap mLoopedSounds;
|
||||||
|
|
||||||
|
bool mUsingSound;
|
||||||
|
|
||||||
std::string lookup(const std::string &soundId,
|
std::string lookup(const std::string &soundId,
|
||||||
float &volume, float &min, float &max);
|
float &volume, float &min, float &max);
|
||||||
void add(const std::string &file,
|
void add(const std::string &file,
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace MWSound
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
class GlobalScripts;
|
class GlobalScripts;
|
||||||
|
class ScriptManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -41,7 +42,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Environment()
|
Environment()
|
||||||
: mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0),
|
: mWorld (0), mSoundManager (0), mGlobalScripts (0), mScriptManager (0), mWindowManager (0),
|
||||||
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0),
|
mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0),
|
||||||
mInputManager (0)
|
mInputManager (0)
|
||||||
{}
|
{}
|
||||||
|
@ -49,6 +50,7 @@ namespace MWWorld
|
||||||
World *mWorld;
|
World *mWorld;
|
||||||
MWSound::SoundManager *mSoundManager;
|
MWSound::SoundManager *mSoundManager;
|
||||||
MWScript::GlobalScripts *mGlobalScripts;
|
MWScript::GlobalScripts *mGlobalScripts;
|
||||||
|
MWScript::ScriptManager *mScriptManager;
|
||||||
MWGui::WindowManager *mWindowManager;
|
MWGui::WindowManager *mWindowManager;
|
||||||
MWMechanics::MechanicsManager *mMechanicsManager;
|
MWMechanics::MechanicsManager *mMechanicsManager;
|
||||||
MWDialogue::DialogueManager *mDialogueManager;
|
MWDialogue::DialogueManager *mDialogueManager;
|
||||||
|
|
|
@ -21,6 +21,18 @@ const std::string WeatherGlobals::mThunderSoundID0 = "Thunder0";
|
||||||
const std::string WeatherGlobals::mThunderSoundID1 = "Thunder1";
|
const std::string WeatherGlobals::mThunderSoundID1 = "Thunder1";
|
||||||
const std::string WeatherGlobals::mThunderSoundID2 = "Thunder2";
|
const std::string WeatherGlobals::mThunderSoundID2 = "Thunder2";
|
||||||
const std::string WeatherGlobals::mThunderSoundID3 = "Thunder3";
|
const std::string WeatherGlobals::mThunderSoundID3 = "Thunder3";
|
||||||
|
const float WeatherGlobals::mSunriseTime = 8;
|
||||||
|
const float WeatherGlobals::mSunsetTime = 18;
|
||||||
|
const float WeatherGlobals::mSunriseDuration = 2;
|
||||||
|
const float WeatherGlobals::mSunsetDuration = 2;
|
||||||
|
const float WeatherGlobals::mWeatherUpdateTime = 20.f;
|
||||||
|
|
||||||
|
|
||||||
|
// morrowind sets these per-weather, but since they are only used by 'thunderstorm'
|
||||||
|
// weather setting anyway, we can just as well set them globally
|
||||||
|
const float WeatherGlobals::mThunderFrequency = .4;
|
||||||
|
const float WeatherGlobals::mThunderThreshold = 0.6;
|
||||||
|
const float WeatherGlobals::mThunderSoundDelay = 0.25;
|
||||||
|
|
||||||
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environment* env) :
|
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environment* env) :
|
||||||
mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0),
|
mHour(14), mCurrentWeather("clear"), mFirstUpdate(true), mWeatherUpdateTime(0),
|
||||||
|
@ -259,7 +271,8 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environmen
|
||||||
blight.mGlareView = 0;
|
blight.mGlareView = 0;
|
||||||
blight.mAmbientLoopSoundID = "blight";
|
blight.mAmbientLoopSoundID = "blight";
|
||||||
mWeatherSettings["blight"] = blight;
|
mWeatherSettings["blight"] = blight;
|
||||||
|
|
||||||
|
/*
|
||||||
Weather snow;
|
Weather snow;
|
||||||
snow.mCloudTexture = "tx_bm_sky_snow.dds";
|
snow.mCloudTexture = "tx_bm_sky_snow.dds";
|
||||||
snow.mCloudsMaximumPercent = 1.0;
|
snow.mCloudsMaximumPercent = 1.0;
|
||||||
|
@ -316,10 +329,14 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, Environmen
|
||||||
blizzard.mGlareView = 0;
|
blizzard.mGlareView = 0;
|
||||||
blizzard.mAmbientLoopSoundID = "BM Blizzard";
|
blizzard.mAmbientLoopSoundID = "BM Blizzard";
|
||||||
mWeatherSettings["blizzard"] = blizzard;
|
mWeatherSettings["blizzard"] = blizzard;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherManager::setWeather(const String& weather, bool instant)
|
void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
{
|
{
|
||||||
|
if (weather == mCurrentWeather && mNextWeather == "")
|
||||||
|
return;
|
||||||
|
|
||||||
if (instant || mFirstUpdate)
|
if (instant || mFirstUpdate)
|
||||||
{
|
{
|
||||||
mNextWeather = "";
|
mNextWeather = "";
|
||||||
|
@ -331,12 +348,12 @@ void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
if (mNextWeather != "")
|
if (mNextWeather != "")
|
||||||
{
|
{
|
||||||
// transition more than 50% finished?
|
// transition more than 50% finished?
|
||||||
if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60) <= 0.5)
|
if (mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600) <= 0.5)
|
||||||
mCurrentWeather = mNextWeather;
|
mCurrentWeather = mNextWeather;
|
||||||
}
|
}
|
||||||
|
|
||||||
mNextWeather = weather;
|
mNextWeather = weather;
|
||||||
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60;
|
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +361,7 @@ WeatherResult WeatherManager::getResult(const String& weather)
|
||||||
{
|
{
|
||||||
const Weather& current = mWeatherSettings[weather];
|
const Weather& current = mWeatherSettings[weather];
|
||||||
WeatherResult result;
|
WeatherResult result;
|
||||||
|
|
||||||
result.mCloudTexture = current.mCloudTexture;
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
result.mCloudBlendFactor = 0;
|
result.mCloudBlendFactor = 0;
|
||||||
result.mCloudOpacity = current.mCloudsMaximumPercent;
|
result.mCloudOpacity = current.mCloudsMaximumPercent;
|
||||||
|
@ -353,16 +370,13 @@ WeatherResult WeatherManager::getResult(const String& weather)
|
||||||
result.mGlareView = current.mGlareView;
|
result.mGlareView = current.mGlareView;
|
||||||
result.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
|
result.mAmbientLoopSoundID = current.mAmbientLoopSoundID;
|
||||||
result.mSunColor = current.mSunDiscSunsetColor;
|
result.mSunColor = current.mSunDiscSunsetColor;
|
||||||
|
|
||||||
const float fade_duration = current.mTransitionDelta * 24.f;
|
result.mNight = (mHour < 6 || mHour > 19);
|
||||||
|
|
||||||
result.mNight = (mHour < 6.f+fade_duration || mHour > 20.f-fade_duration);
|
|
||||||
|
|
||||||
result.mFogDepth = result.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
|
result.mFogDepth = result.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
|
||||||
|
|
||||||
// night
|
// night
|
||||||
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration)
|
if (mHour <= 5.5f || mHour >= 21)
|
||||||
|| mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration))
|
|
||||||
{
|
{
|
||||||
result.mFogColor = current.mFogNightColor;
|
result.mFogColor = current.mFogNightColor;
|
||||||
result.mAmbientColor = current.mAmbientNightColor;
|
result.mAmbientColor = current.mAmbientNightColor;
|
||||||
|
@ -370,82 +384,68 @@ WeatherResult WeatherManager::getResult(const String& weather)
|
||||||
result.mSkyColor = current.mSkyNightColor;
|
result.mSkyColor = current.mSkyNightColor;
|
||||||
result.mNightFade = 1.f;
|
result.mNightFade = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sunrise
|
// sunrise
|
||||||
else if (mHour >= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration) && mHour <= WeatherGlobals::mSunriseTime)
|
else if (mHour >= 5.5f && mHour <= 9)
|
||||||
{
|
{
|
||||||
if (mHour <= (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration))
|
if (mHour <= 6)
|
||||||
{
|
{
|
||||||
// fade in
|
// fade in
|
||||||
float advance = (WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration+fade_duration)-mHour;
|
float advance = 6-mHour;
|
||||||
float factor = (advance / fade_duration);
|
float factor = advance / 0.5f;
|
||||||
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor);
|
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor);
|
||||||
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor);
|
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor);
|
||||||
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor);
|
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor);
|
||||||
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor);
|
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor);
|
||||||
result.mNightFade = factor;
|
result.mNightFade = factor;
|
||||||
}
|
}
|
||||||
else if (mHour >= (WeatherGlobals::mSunriseTime-fade_duration))
|
else //if (mHour >= 6)
|
||||||
{
|
{
|
||||||
// fade out
|
// fade out
|
||||||
float advance = mHour-(WeatherGlobals::mSunriseTime-fade_duration);
|
float advance = mHour-6;
|
||||||
float factor = advance / fade_duration;
|
float factor = advance / 3.f;
|
||||||
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor);
|
result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor);
|
||||||
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor);
|
result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor);
|
||||||
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor);
|
result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor);
|
||||||
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor);
|
result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
result.mFogColor = current.mFogSunriseColor;
|
|
||||||
result.mAmbientColor = current.mAmbientSunriseColor;
|
|
||||||
result.mSunColor = current.mSunSunriseColor;
|
|
||||||
result.mSkyColor = current.mSkySunriseColor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// day
|
// day
|
||||||
else if (mHour >= (WeatherGlobals::mSunriseTime) && mHour <= (WeatherGlobals::mSunsetTime))
|
else if (mHour >= 9 && mHour <= 17)
|
||||||
{
|
{
|
||||||
result.mFogColor = current.mFogDayColor;
|
result.mFogColor = current.mFogDayColor;
|
||||||
result.mAmbientColor = current.mAmbientDayColor;
|
result.mAmbientColor = current.mAmbientDayColor;
|
||||||
result.mSunColor = current.mSunDayColor;
|
result.mSunColor = current.mSunDayColor;
|
||||||
result.mSkyColor = current.mSkyDayColor;
|
result.mSkyColor = current.mSkyDayColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sunset
|
// sunset
|
||||||
else if (mHour >= (WeatherGlobals::mSunsetTime) && mHour <= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration))
|
else if (mHour >= 17 && mHour <= 21)
|
||||||
{
|
{
|
||||||
if (mHour <= (WeatherGlobals::mSunsetTime+fade_duration))
|
if (mHour <= 19)
|
||||||
{
|
{
|
||||||
// fade in
|
// fade in
|
||||||
float advance = (WeatherGlobals::mSunsetTime+fade_duration)-mHour;
|
float advance = 19-mHour;
|
||||||
float factor = (advance / fade_duration);
|
float factor = (advance / 2);
|
||||||
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor);
|
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor);
|
||||||
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor);
|
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor);
|
||||||
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor);
|
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor);
|
||||||
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor);
|
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor);
|
||||||
}
|
}
|
||||||
else if (mHour >= (WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration))
|
else //if (mHour >= 19)
|
||||||
{
|
{
|
||||||
// fade out
|
// fade out
|
||||||
float advance = mHour-(WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration-fade_duration);
|
float advance = mHour-19;
|
||||||
float factor = advance / fade_duration;
|
float factor = advance / 2.f;
|
||||||
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor);
|
result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor);
|
||||||
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor);
|
result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor);
|
||||||
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor);
|
result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor);
|
||||||
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor);
|
result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor);
|
||||||
result.mNightFade = factor;
|
result.mNightFade = factor;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
result.mFogColor = current.mFogSunsetColor;
|
|
||||||
result.mAmbientColor = current.mAmbientSunsetColor;
|
|
||||||
result.mSunColor = current.mSunSunsetColor;
|
|
||||||
result.mSkyColor = current.mSkySunsetColor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,43 +454,36 @@ WeatherResult WeatherManager::transition(float factor)
|
||||||
const WeatherResult& current = getResult(mCurrentWeather);
|
const WeatherResult& current = getResult(mCurrentWeather);
|
||||||
const WeatherResult& other = getResult(mNextWeather);
|
const WeatherResult& other = getResult(mNextWeather);
|
||||||
WeatherResult result;
|
WeatherResult result;
|
||||||
|
|
||||||
result.mCloudTexture = current.mCloudTexture;
|
result.mCloudTexture = current.mCloudTexture;
|
||||||
result.mNextCloudTexture = other.mCloudTexture;
|
result.mNextCloudTexture = other.mCloudTexture;
|
||||||
result.mCloudBlendFactor = factor;
|
result.mCloudBlendFactor = factor;
|
||||||
|
|
||||||
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
||||||
result.mFogColor = lerp(current.mFogColor, other.mFogColor);
|
result.mFogColor = lerp(current.mFogColor, other.mFogColor);
|
||||||
result.mSunColor = lerp(current.mSunColor, other.mSunColor);
|
result.mSunColor = lerp(current.mSunColor, other.mSunColor);
|
||||||
result.mSkyColor = lerp(current.mSkyColor, other.mSkyColor);
|
result.mSkyColor = lerp(current.mSkyColor, other.mSkyColor);
|
||||||
|
|
||||||
result.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor);
|
result.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor);
|
||||||
result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor);
|
result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor);
|
||||||
result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth);
|
result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth);
|
||||||
result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed);
|
result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed);
|
||||||
result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed);
|
//result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed);
|
||||||
|
result.mCloudSpeed = current.mCloudSpeed;
|
||||||
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
||||||
result.mGlareView = lerp(current.mGlareView, other.mGlareView);
|
result.mGlareView = lerp(current.mGlareView, other.mGlareView);
|
||||||
|
|
||||||
result.mNight = current.mNight;
|
result.mNight = current.mNight;
|
||||||
|
|
||||||
// sound change behaviour:
|
|
||||||
// if 'other' has a new sound, switch to it after 1/2 of the transition length
|
|
||||||
if (other.mAmbientLoopSoundID != "")
|
|
||||||
result.mAmbientLoopSoundID = factor>0.5 ? other.mAmbientLoopSoundID : current.mAmbientLoopSoundID;
|
|
||||||
// if 'current' has a sound and 'other' does not have a sound, turn off the sound immediately
|
|
||||||
else if (current.mAmbientLoopSoundID != "")
|
|
||||||
result.mAmbientLoopSoundID = "";
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherManager::update(float duration)
|
void WeatherManager::update(float duration)
|
||||||
{
|
{
|
||||||
mWeatherUpdateTime -= duration;
|
mWeatherUpdateTime -= duration * mEnvironment->mWorld->getTimeScaleFactor();
|
||||||
|
|
||||||
bool exterior = (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior());
|
bool exterior = (mEnvironment->mWorld->isCellExterior() || mEnvironment->mWorld->isCellQuasiExterior());
|
||||||
|
|
||||||
if (exterior)
|
if (exterior)
|
||||||
{
|
{
|
||||||
std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region;
|
std::string regionstr = mEnvironment->mWorld->getPlayer().getPlayer().getCell()->cell->region;
|
||||||
|
@ -499,17 +492,17 @@ void WeatherManager::update(float duration)
|
||||||
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
||||||
{
|
{
|
||||||
mCurrentRegion = regionstr;
|
mCurrentRegion = regionstr;
|
||||||
mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*60.f;
|
mWeatherUpdateTime = WeatherGlobals::mWeatherUpdateTime*3600;
|
||||||
|
|
||||||
std::string weather;
|
std::string weather;
|
||||||
|
|
||||||
if (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
|
if (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
|
||||||
weather = mRegionOverrides[regionstr];
|
weather = mRegionOverrides[regionstr];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get weather probabilities for the current region
|
// get weather probabilities for the current region
|
||||||
const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr);
|
const ESM::Region *region = mEnvironment->mWorld->getStore().regions.find (regionstr);
|
||||||
|
|
||||||
float clear = region->data.clear/255.f;
|
float clear = region->data.clear/255.f;
|
||||||
float cloudy = region->data.cloudy/255.f;
|
float cloudy = region->data.cloudy/255.f;
|
||||||
float foggy = region->data.foggy/255.f;
|
float foggy = region->data.foggy/255.f;
|
||||||
|
@ -518,86 +511,84 @@ void WeatherManager::update(float duration)
|
||||||
float thunder = region->data.thunder/255.f;
|
float thunder = region->data.thunder/255.f;
|
||||||
float ash = region->data.ash/255.f;
|
float ash = region->data.ash/255.f;
|
||||||
float blight = region->data.blight/255.f;
|
float blight = region->data.blight/255.f;
|
||||||
float snow = region->data.a/255.f;
|
//float snow = region->data.a/255.f;
|
||||||
float blizzard = region->data.b/255.f;
|
//float blizzard = region->data.b/255.f;
|
||||||
|
|
||||||
// re-scale to 100 percent
|
// re-scale to 100 percent
|
||||||
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight+snow+blizzard;
|
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard;
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
float random = ((rand()%100)/100.f) * total;
|
float random = ((rand()%100)/100.f) * total;
|
||||||
|
|
||||||
if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
//if (random > snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "blizzard";
|
// weather = "blizzard";
|
||||||
else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
//else if (random > blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "snow";
|
// weather = "snow";
|
||||||
else if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear)
|
/*else*/ if (random > ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "blight";
|
weather = "blight";
|
||||||
else if (random >= thunder+rain+overcast+foggy+cloudy+clear)
|
else if (random > thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "ashstorm";
|
weather = "ashstorm";
|
||||||
else if (random >= rain+overcast+foggy+cloudy+clear)
|
else if (random > rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "thunderstorm";
|
weather = "thunderstorm";
|
||||||
else if (random >= overcast+foggy+cloudy+clear)
|
else if (random > overcast+foggy+cloudy+clear)
|
||||||
weather = "rain";
|
weather = "rain";
|
||||||
else if (random >= foggy+cloudy+clear)
|
else if (random > foggy+cloudy+clear)
|
||||||
weather = "overcast";
|
weather = "overcast";
|
||||||
else if (random >= cloudy+clear)
|
else if (random > cloudy+clear)
|
||||||
weather = "foggy";
|
weather = "foggy";
|
||||||
else if (random >= clear)
|
else if (random > clear)
|
||||||
weather = "cloudy";
|
weather = "cloudy";
|
||||||
else
|
else
|
||||||
weather = "clear";
|
weather = "clear";
|
||||||
}
|
}
|
||||||
|
|
||||||
setWeather(weather, false);
|
setWeather(weather, false);
|
||||||
/*
|
|
||||||
std::cout << "roll result: " << random << std::endl;
|
|
||||||
|
|
||||||
std::cout << regionstr << " weather probabilities: " << clear << " " << cloudy << " " << foggy << " "
|
|
||||||
<< overcast << " " << rain << " " << thunder << " " << ash << " " << blight << " " << snow << " "
|
|
||||||
<< blizzard << std::endl;
|
|
||||||
|
|
||||||
std::cout << "New weather : " << weather << std::endl;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherResult result;
|
WeatherResult result;
|
||||||
|
|
||||||
if (mNextWeather != "")
|
if (mNextWeather != "")
|
||||||
{
|
{
|
||||||
mRemainingTransitionTime -= duration;
|
mRemainingTransitionTime -= duration * mEnvironment->mWorld->getTimeScaleFactor();
|
||||||
if (mRemainingTransitionTime < 0)
|
if (mRemainingTransitionTime < 0)
|
||||||
{
|
{
|
||||||
mCurrentWeather = mNextWeather;
|
mCurrentWeather = mNextWeather;
|
||||||
mNextWeather = "";
|
mNextWeather = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNextWeather != "")
|
if (mNextWeather != "")
|
||||||
result = transition(1-(mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*60)));
|
result = transition(1-(mRemainingTransitionTime/(mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600)));
|
||||||
else
|
else
|
||||||
result = getResult(mCurrentWeather);
|
result = getResult(mCurrentWeather);
|
||||||
|
|
||||||
mRendering->configureFog(result.mFogDepth, result.mFogColor);
|
mRendering->configureFog(result.mFogDepth, result.mFogColor);
|
||||||
|
|
||||||
// disable sun during night
|
// disable sun during night
|
||||||
if (mHour >= WeatherGlobals::mSunsetTime+WeatherGlobals::mSunsetDuration
|
if (mHour >= 20 || mHour <= 6.f)
|
||||||
|| mHour <= WeatherGlobals::mSunriseTime-WeatherGlobals::mSunriseDuration)
|
|
||||||
mRendering->getSkyManager()->sunDisable();
|
mRendering->getSkyManager()->sunDisable();
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// during day, calculate sun angle
|
|
||||||
float height = 1-std::abs(((mHour-13)/7.f));
|
|
||||||
int facing = mHour > 13.f ? 1 : -1;
|
|
||||||
Vector3 final(
|
|
||||||
(1-height)*facing,
|
|
||||||
(1-height)*facing,
|
|
||||||
height);
|
|
||||||
mRendering->setSunDirection(final);
|
|
||||||
|
|
||||||
mRendering->getSkyManager()->sunEnable();
|
mRendering->getSkyManager()->sunEnable();
|
||||||
}
|
|
||||||
|
// sun angle
|
||||||
|
float height;
|
||||||
|
|
||||||
|
// rise at 6, set at 20
|
||||||
|
if (mHour >= 6 && mHour <= 20)
|
||||||
|
height = 1-std::abs(((mHour-13)/7.f));
|
||||||
|
else if (mHour > 20)
|
||||||
|
height = (mHour-20.f)/4.f;
|
||||||
|
else //if (mHour > 0 && mHour < 6)
|
||||||
|
height = 1-(mHour/6.f);
|
||||||
|
|
||||||
|
int facing = (mHour > 13.f) ? 1 : -1;
|
||||||
|
|
||||||
|
Vector3 final(
|
||||||
|
(1-height)*facing,
|
||||||
|
(1-height)*facing,
|
||||||
|
height);
|
||||||
|
mRendering->setSunDirection(final);
|
||||||
|
|
||||||
// moon calculations
|
// moon calculations
|
||||||
float night;
|
float night;
|
||||||
if (mHour >= 14)
|
if (mHour >= 14)
|
||||||
|
@ -606,9 +597,9 @@ void WeatherManager::update(float duration)
|
||||||
night = mHour+10;
|
night = mHour+10;
|
||||||
else
|
else
|
||||||
night = 0;
|
night = 0;
|
||||||
|
|
||||||
night /= 20.f;
|
night /= 20.f;
|
||||||
|
|
||||||
if (night != 0)
|
if (night != 0)
|
||||||
{
|
{
|
||||||
float moonHeight = 1-std::abs((night-0.5)*2);
|
float moonHeight = 1-std::abs((night-0.5)*2);
|
||||||
|
@ -617,17 +608,17 @@ void WeatherManager::update(float duration)
|
||||||
(1-moonHeight)*facing,
|
(1-moonHeight)*facing,
|
||||||
(1-moonHeight)*facing,
|
(1-moonHeight)*facing,
|
||||||
moonHeight);
|
moonHeight);
|
||||||
|
|
||||||
Vector3 secunda(
|
Vector3 secunda(
|
||||||
(1-moonHeight)*facing*0.8,
|
(1-moonHeight)*facing*0.8,
|
||||||
(1-moonHeight)*facing*1.25,
|
(1-moonHeight)*facing*1.25,
|
||||||
moonHeight);
|
moonHeight);
|
||||||
|
|
||||||
mRendering->getSkyManager()->setMasserDirection(masser);
|
mRendering->getSkyManager()->setMasserDirection(masser);
|
||||||
mRendering->getSkyManager()->setSecundaDirection(secunda);
|
mRendering->getSkyManager()->setSecundaDirection(secunda);
|
||||||
mRendering->getSkyManager()->masserEnable();
|
mRendering->getSkyManager()->masserEnable();
|
||||||
mRendering->getSkyManager()->secundaEnable();
|
mRendering->getSkyManager()->secundaEnable();
|
||||||
|
|
||||||
float hour_fade;
|
float hour_fade;
|
||||||
if (mHour >= 7.f && mHour <= 14.f)
|
if (mHour >= 7.f && mHour <= 14.f)
|
||||||
hour_fade = 1-(mHour-7)/3.f;
|
hour_fade = 1-(mHour-7)/3.f;
|
||||||
|
@ -635,28 +626,28 @@ void WeatherManager::update(float duration)
|
||||||
hour_fade = mHour-14;
|
hour_fade = mHour-14;
|
||||||
else
|
else
|
||||||
hour_fade = 1;
|
hour_fade = 1;
|
||||||
|
|
||||||
float secunda_angle_fade;
|
float secunda_angle_fade;
|
||||||
float masser_angle_fade;
|
float masser_angle_fade;
|
||||||
float angle = moonHeight*90.f;
|
float angle = moonHeight*90.f;
|
||||||
|
|
||||||
if (angle >= 30 && angle <= 50)
|
if (angle >= 30 && angle <= 50)
|
||||||
secunda_angle_fade = (angle-30)/20.f;
|
secunda_angle_fade = (angle-30)/20.f;
|
||||||
else if (angle <30)
|
else if (angle <30)
|
||||||
secunda_angle_fade = 0.f;
|
secunda_angle_fade = 0.f;
|
||||||
else
|
else
|
||||||
secunda_angle_fade = 1.f;
|
secunda_angle_fade = 1.f;
|
||||||
|
|
||||||
if (angle >= 40 && angle <= 50)
|
if (angle >= 40 && angle <= 50)
|
||||||
masser_angle_fade = (angle-40)/10.f;
|
masser_angle_fade = (angle-40)/10.f;
|
||||||
else if (angle <40)
|
else if (angle <40)
|
||||||
masser_angle_fade = 0.f;
|
masser_angle_fade = 0.f;
|
||||||
else
|
else
|
||||||
masser_angle_fade = 1.f;
|
masser_angle_fade = 1.f;
|
||||||
|
|
||||||
masser_angle_fade *= hour_fade;
|
masser_angle_fade *= hour_fade;
|
||||||
secunda_angle_fade *= hour_fade;
|
secunda_angle_fade *= hour_fade;
|
||||||
|
|
||||||
mRendering->getSkyManager()->setMasserFade(masser_angle_fade);
|
mRendering->getSkyManager()->setMasserFade(masser_angle_fade);
|
||||||
mRendering->getSkyManager()->setSecundaFade(secunda_angle_fade);
|
mRendering->getSkyManager()->setSecundaFade(secunda_angle_fade);
|
||||||
}
|
}
|
||||||
|
@ -665,7 +656,7 @@ void WeatherManager::update(float duration)
|
||||||
mRendering->getSkyManager()->masserDisable();
|
mRendering->getSkyManager()->masserDisable();
|
||||||
mRendering->getSkyManager()->secundaDisable();
|
mRendering->getSkyManager()->secundaDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCurrentWeather == "thunderstorm" && mNextWeather == "" && exterior)
|
if (mCurrentWeather == "thunderstorm" && mNextWeather == "" && exterior)
|
||||||
{
|
{
|
||||||
if (mThunderFlash > 0)
|
if (mThunderFlash > 0)
|
||||||
|
@ -684,7 +675,7 @@ void WeatherManager::update(float duration)
|
||||||
mEnvironment->mSoundManager->playSound(soundname, 1.0, 1.0);
|
mEnvironment->mSoundManager->playSound(soundname, 1.0, 1.0);
|
||||||
mThunderSoundDelay = 1000;
|
mThunderSoundDelay = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
mThunderFlash -= duration;
|
mThunderFlash -= duration;
|
||||||
if (mThunderFlash > 0)
|
if (mThunderFlash > 0)
|
||||||
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
||||||
|
@ -703,20 +694,20 @@ void WeatherManager::update(float duration)
|
||||||
if (mThunderChance >= mThunderChanceNeeded)
|
if (mThunderChance >= mThunderChanceNeeded)
|
||||||
{
|
{
|
||||||
mThunderFlash = WeatherGlobals::mThunderThreshold;
|
mThunderFlash = WeatherGlobals::mThunderThreshold;
|
||||||
|
|
||||||
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold );
|
||||||
|
|
||||||
mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay;
|
mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mRendering->getSkyManager()->setThunder(0.f);
|
mRendering->getSkyManager()->setThunder(0.f);
|
||||||
|
|
||||||
mRendering->setAmbientColour(result.mAmbientColor);
|
mRendering->setAmbientColour(result.mAmbientColor);
|
||||||
mRendering->sunEnable();
|
mRendering->sunEnable();
|
||||||
mRendering->setSunColour(result.mSunColor);
|
mRendering->setSunColour(result.mSunColor);
|
||||||
|
|
||||||
mRendering->getSkyManager()->setWeather(result);
|
mRendering->getSkyManager()->setWeather(result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -765,15 +756,6 @@ void WeatherManager::update(float duration)
|
||||||
|
|
||||||
void WeatherManager::setHour(const float hour)
|
void WeatherManager::setHour(const float hour)
|
||||||
{
|
{
|
||||||
// accelerate a bit for testing
|
|
||||||
/*
|
|
||||||
mHour += 0.005;
|
|
||||||
|
|
||||||
if (mHour >= 24.f) mHour = 0.f;
|
|
||||||
|
|
||||||
std::cout << "hour " << mHour << std::endl;
|
|
||||||
*/
|
|
||||||
|
|
||||||
mHour = hour;
|
mHour = hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,18 +95,18 @@ namespace MWWorld
|
||||||
Script Color=255,20,20
|
Script Color=255,20,20
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const float mSunriseTime = 8;
|
static const float mSunriseTime;
|
||||||
static const float mSunsetTime = 18;
|
static const float mSunsetTime;
|
||||||
static const float mSunriseDuration = 2;
|
static const float mSunriseDuration;
|
||||||
static const float mSunsetDuration = 2;
|
static const float mSunsetDuration;
|
||||||
|
|
||||||
static const float mWeatherUpdateTime = 20.f;
|
static const float mWeatherUpdateTime;
|
||||||
|
|
||||||
// morrowind sets these per-weather, but since they are only used by 'thunderstorm'
|
// morrowind sets these per-weather, but since they are only used by 'thunderstorm'
|
||||||
// weather setting anyway, we can just as well set them globally
|
// weather setting anyway, we can just as well set them globally
|
||||||
static const float mThunderFrequency = .4;
|
static const float mThunderFrequency;
|
||||||
static const float mThunderThreshold = 0.6;
|
static const float mThunderThreshold;
|
||||||
static const float mThunderSoundDelay = 0.25;
|
static const float mThunderSoundDelay;
|
||||||
static const std::string mThunderSoundID0;
|
static const std::string mThunderSoundID0;
|
||||||
static const std::string mThunderSoundID1;
|
static const std::string mThunderSoundID1;
|
||||||
static const std::string mThunderSoundID2;
|
static const std::string mThunderSoundID2;
|
||||||
|
|
|
@ -478,7 +478,7 @@ namespace MWWorld
|
||||||
|
|
||||||
float World::getTimeScaleFactor() const
|
float World::getTimeScaleFactor() const
|
||||||
{
|
{
|
||||||
return mGlobalVariables->getInt ("timescale");
|
return mGlobalVariables->getFloat ("timescale");
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
||||||
|
|
|
@ -405,10 +405,22 @@ macro(ogre_find_plugin PLUGIN HEADER)
|
||||||
set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}")
|
set(OGRE_${PLUGIN}_LIBRARY_NAMES "${PLUGIN}${OGRE_LIB_SUFFIX}")
|
||||||
get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES)
|
get_debug_names(OGRE_${PLUGIN}_LIBRARY_NAMES)
|
||||||
set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK})
|
set(OGRE_${PLUGIN}_LIBRARY_FWK ${OGRE_LIBRARY_FWK})
|
||||||
|
# Search for release plugins in OGRE dir with version suffix
|
||||||
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
|
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
|
||||||
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
|
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE-${OGRE_VERSION} opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
|
||||||
|
if(NOT EXISTS "${OGRE_${PLUGIN}_LIBRARY_REL}")
|
||||||
|
# Search for release plugins in OGRE dir without version suffix
|
||||||
|
find_library(OGRE_${PLUGIN}_LIBRARY_REL NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES}
|
||||||
|
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt release release/opt relwithdebinfo relwithdebinfo/opt minsizerel minsizerel/opt)
|
||||||
|
endif()
|
||||||
|
# Search for debug plugins in OGRE dir with version suffix
|
||||||
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
|
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
|
||||||
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt)
|
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE-${OGRE_VERSION} opt debug debug/opt)
|
||||||
|
if(NOT EXISTS "${OGRE_${PLUGIN}_LIBRARY_DBG}")
|
||||||
|
# Search for debug plugins in OGRE dir without version suffix
|
||||||
|
find_library(OGRE_${PLUGIN}_LIBRARY_DBG NAMES ${OGRE_${PLUGIN}_LIBRARY_NAMES_DBG}
|
||||||
|
HINTS ${OGRE_LIBRARY_DIRS} PATH_SUFFIXES "" OGRE opt debug debug/opt)
|
||||||
|
endif()
|
||||||
make_library_set(OGRE_${PLUGIN}_LIBRARY)
|
make_library_set(OGRE_${PLUGIN}_LIBRARY)
|
||||||
|
|
||||||
if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR)
|
if (OGRE_${PLUGIN}_LIBRARY OR OGRE_${PLUGIN}_INCLUDE_DIR)
|
||||||
|
@ -441,9 +453,13 @@ macro(ogre_find_plugin PLUGIN HEADER)
|
||||||
PATH_SUFFIXES "" bin bin/debug debug)
|
PATH_SUFFIXES "" bin bin/debug debug)
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH)
|
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_REL} PATH)
|
||||||
set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)")
|
# For some reason this fails
|
||||||
|
#set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (release)")
|
||||||
|
set(OGRE_PLUGIN_DIR_REL ${OGRE_PLUGIN_DIR_TMP})
|
||||||
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH)
|
get_filename_component(OGRE_PLUGIN_DIR_TMP ${OGRE_${PLUGIN}_LIBRARY_DBG} PATH)
|
||||||
set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)")
|
# Same here
|
||||||
|
#set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP} CACHE STRING "Ogre plugin dir (debug)")
|
||||||
|
set(OGRE_PLUGIN_DIR_DBG ${OGRE_PLUGIN_DIR_TMP})
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -639,7 +639,7 @@ namespace Compiler
|
||||||
std::vector<Interpreter::Type_Code>& code, bool invert)
|
std::vector<Interpreter::Type_Code>& code, bool invert)
|
||||||
{
|
{
|
||||||
bool optional = false;
|
bool optional = false;
|
||||||
bool optionalCount = 0;
|
int optionalCount = 0;
|
||||||
|
|
||||||
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
||||||
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Compiler
|
||||||
mLineParser.reset();
|
mLineParser.reset();
|
||||||
if (mLineParser.parseName (name, loc, scanner))
|
if (mLineParser.parseName (name, loc, scanner))
|
||||||
scanner.scan (mLineParser);
|
scanner.scan (mLineParser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,22 +34,22 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
mControlParser.reset();
|
mControlParser.reset();
|
||||||
if (mControlParser.parseKeyword (keyword, loc, scanner))
|
if (mControlParser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (mControlParser);
|
scanner.scan (mControlParser);
|
||||||
|
|
||||||
mControlParser.appendCode (mOutput.getCode());
|
mControlParser.appendCode (mOutput.getCode());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyword==Scanner::K_end && mEnd)
|
if (keyword==Scanner::K_end && mEnd)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLineParser.reset();
|
mLineParser.reset();
|
||||||
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (mLineParser);
|
scanner.scan (mLineParser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (code==Scanner::S_newline) // empty line
|
if (code==Scanner::S_newline) // empty line
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
mLineParser.reset();
|
mLineParser.reset();
|
||||||
if (mLineParser.parseSpecial (code, loc, scanner))
|
if (mLineParser.parseSpecial (code, loc, scanner))
|
||||||
scanner.scan (mLineParser);
|
scanner.scan (mLineParser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,4 +77,3 @@ namespace Compiler
|
||||||
mOutput.clear();
|
mOutput.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,11 @@ namespace Compiler
|
||||||
mState = CommaState;
|
mState = CommaState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (code==Scanner::S_newline && mState==StartState)
|
||||||
|
{
|
||||||
|
scanner.putbackSpecial (code, loc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
1
extern/mygui_3.0.1/CMakeLists.txt
vendored
1
extern/mygui_3.0.1/CMakeLists.txt
vendored
|
@ -34,6 +34,7 @@ configure_file("${SDIR}/openmw_chargen_class_description_layout.xml" "${DDIR}/op
|
||||||
configure_file("${SDIR}/openmw_chargen_birth_layout.xml" "${DDIR}/openmw_chargen_birth_layout.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_chargen_birth_layout.xml" "${DDIR}/openmw_chargen_birth_layout.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_chargen_review_layout.xml" "${DDIR}/openmw_chargen_review_layout.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_chargen_review_layout.xml" "${DDIR}/openmw_chargen_review_layout.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_dialogue_window_layout.xml" "${DDIR}/openmw_dialogue_window_layout.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_dialogue_window_layout.xml" "${DDIR}/openmw_dialogue_window_layout.xml" COPYONLY)
|
||||||
|
configure_file("${SDIR}/openmw_dialogue_window_skin.xml" "${DDIR}/openmw_dialogue_window_skin.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_inventory_window_layout.xml" "${DDIR}/openmw_inventory_window_layout.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_inventory_window_layout.xml" "${DDIR}/openmw_inventory_window_layout.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_mainmenu_layout.xml" "${DDIR}/openmw_mainmenu_layout.xml" COPYONLY)
|
||||||
|
|
1
extern/mygui_3.0.1/openmw_resources/core.xml
vendored
1
extern/mygui_3.0.1/openmw_resources/core.xml
vendored
|
@ -20,6 +20,7 @@
|
||||||
<List file="openmw_mainmenu_skin.xml" group="General"/>
|
<List file="openmw_mainmenu_skin.xml" group="General"/>
|
||||||
<List file="openmw_console.skin.xml" group="General"/>
|
<List file="openmw_console.skin.xml" group="General"/>
|
||||||
<List file="openmw_journal_skin.xml" group="General"/>
|
<List file="openmw_journal_skin.xml" group="General"/>
|
||||||
|
<List file="openmw_dialogue_window_skin.xml" group="General"/>
|
||||||
</MyGUI>
|
</MyGUI>
|
||||||
|
|
||||||
</MyGUI>
|
</MyGUI>
|
||||||
|
|
|
@ -17,8 +17,13 @@
|
||||||
<Property key="Edit_VisibleVScroll" value="1" />
|
<Property key="Edit_VisibleVScroll" value="1" />
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
|
<!-- The disposition bar-->
|
||||||
|
<Widget type="Progress" skin="MW_EnergyBar_Blue" position="432 39 132 18"
|
||||||
|
align="Right Top" name="Disposition">
|
||||||
|
<Widget type="Edit" skin="MW_DispositionEdit" position_real = "0.25 0 0.5 1" name = "DispositionText"/>
|
||||||
|
</Widget>
|
||||||
<!-- The list of topics -->
|
<!-- The list of topics -->
|
||||||
<Widget type="List" skin="MW_List" position="432 39 132 341" name="TopicsList">
|
<Widget type="List" skin="MW_List" position="432 62 132 318" name="TopicsList">
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<!-- The Goodbye button -->
|
<!-- The Goodbye button -->
|
||||||
|
|
18
extern/mygui_3.0.1/openmw_resources/openmw_dialogue_window_skin.xml
vendored
Normal file
18
extern/mygui_3.0.1/openmw_resources/openmw_dialogue_window_skin.xml
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<MyGUI type="Skin">
|
||||||
|
|
||||||
|
<Skin name = "MW_DispEdit" size = "10 10">
|
||||||
|
<Property key="FontName" value = "MonoFont" />
|
||||||
|
<Property key="AlignText" value = "Left Top" />
|
||||||
|
<Property key="Colour" value = "0000FF" />
|
||||||
|
<!--Property key="Pointer" value = "beam" /-->
|
||||||
|
<BasisSkin type="EditText" offset = "0 0 10 10" align = "Stretch"/>
|
||||||
|
</Skin>
|
||||||
|
|
||||||
|
<Skin name="MW_DispositionEdit" size="0 0 50 50">
|
||||||
|
<Property key="WordWrap" value = "true" />
|
||||||
|
<Child type="Widget" skin="MW_DispEdit" offset="0 0 35 10" align = "ALIGN_STRETCH" name = "Client"/>
|
||||||
|
<!--Child type="VScroll" skin="VScroll" offset = "35 0 15 50" align = "Right VStretch" name = "VScroll"/-->
|
||||||
|
</Skin>
|
||||||
|
</MyGUI>
|
39
readme.txt
39
readme.txt
|
@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
|
||||||
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
||||||
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
||||||
|
|
||||||
Version: 0.12.0
|
Version: 0.13.0
|
||||||
License: GPL (see GPL3.txt for more information)
|
License: GPL (see GPL3.txt for more information)
|
||||||
Website: http://www.openmw.org
|
Website: http://www.openmw.org
|
||||||
|
|
||||||
|
@ -96,11 +96,15 @@ athile
|
||||||
Cris “Mirceam” Mihalache
|
Cris “Mirceam” Mihalache
|
||||||
gugus / gus
|
gugus / gus
|
||||||
Jacob “Yacoby” Essex
|
Jacob “Yacoby” Essex
|
||||||
|
Jannik “scrawl” Heller
|
||||||
Jason “jhooks” Hooks
|
Jason “jhooks” Hooks
|
||||||
|
Karl-Felix “k1ll” Glatzer
|
||||||
Lukasz “lgro” Gromanowski
|
Lukasz “lgro” Gromanowski
|
||||||
Marc “Zini” Zinnschlag
|
Marc “Zini” Zinnschlag
|
||||||
|
Michael “werdanith” Papageorgiou
|
||||||
Nikolay “corristo” Kasyanov
|
Nikolay “corristo” Kasyanov
|
||||||
Pieter “pvdk” van der Kloet
|
Pieter “pvdk” van der Kloet
|
||||||
|
Roman "Kromgart" Melnik
|
||||||
Sebastian “swick” Wick
|
Sebastian “swick” Wick
|
||||||
|
|
||||||
Retired Developers:
|
Retired Developers:
|
||||||
|
@ -110,7 +114,6 @@ Diggory Hardy
|
||||||
Jan Borsodi
|
Jan Borsodi
|
||||||
Jan-Peter “peppe” Nilsson
|
Jan-Peter “peppe” Nilsson
|
||||||
Josua Grawitter
|
Josua Grawitter
|
||||||
Karl-Felix “k1ll” Glatzer
|
|
||||||
Nicolay Korslund
|
Nicolay Korslund
|
||||||
sergoz
|
sergoz
|
||||||
Star-Demon
|
Star-Demon
|
||||||
|
@ -125,6 +128,38 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil
|
||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
0.13.0
|
||||||
|
|
||||||
|
Bug #145: Fixed sound problems after cell change
|
||||||
|
Bug #179: Pressing space in console triggers activation
|
||||||
|
Bug #186: CMake doesn't use the debug versions of Ogre libraries on Linux
|
||||||
|
Bug #189: ASCII 16 character added to console on it's activation on Mac OS X
|
||||||
|
Bug #190: Case Folding fails with music files
|
||||||
|
Bug #192: Keypresses write Text into Console no matter which gui element is active
|
||||||
|
Bug #196: Collision shapes out of place
|
||||||
|
Bug #202: ESMTool doesn't not work with localised ESM files anymore
|
||||||
|
Bug #203: Torch lights only visible on short distance
|
||||||
|
Bug #207: Ogre.log not written
|
||||||
|
Bug #209: Sounds do not play
|
||||||
|
Bug #210: Ogre crash at Dren plantation
|
||||||
|
Bug #214: Unsupported file format version
|
||||||
|
Feature #9: NPC Dialogue Window
|
||||||
|
Feature #16/42: New sky/weather implementation
|
||||||
|
Feature #40: Fading
|
||||||
|
Feature #48: NPC Dialogue System
|
||||||
|
Feature #117: Equipping Items (backend only, no GUI yet, no rendering of equipped items yet)
|
||||||
|
Feature #161: Load REC_PGRD records
|
||||||
|
Feature #195: Wireframe-mode
|
||||||
|
Feature #198/199: Various sound effects
|
||||||
|
Feature #206: Allow picking data path from launcher if non is set
|
||||||
|
Task #108: Refactor window manager class
|
||||||
|
Task #172: Sound Manager Cleanup
|
||||||
|
Task #173: Create OpenEngine systems in the appropriate manager classes
|
||||||
|
Task #184: Adjust MSVC and gcc warning levels
|
||||||
|
Task #185: RefData rewrite
|
||||||
|
Task #201: Workaround for transparency issues
|
||||||
|
Task #208: silenced esm_reader.hpp warning
|
||||||
|
|
||||||
0.12.0
|
0.12.0
|
||||||
|
|
||||||
Bug #154: FPS Drop
|
Bug #154: FPS Drop
|
||||||
|
|
Loading…
Reference in a new issue