Merge branch 'master' into mygui

actorid
scrawl 13 years ago
commit 66baf9ec81

@ -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
fileReader.setEncoding(variables["encoding"].as<std::string>());
fileReader.open(iter->second.string());
// First we fill the availableMasters and the mMastersWidget // First we fill the availableMasters and the mMastersWidget
ESMReader::MasterList mlist = fileReader.getMasters(); ESMReader::MasterList mlist = fileReader.getMasters();
for (unsigned int i = 0; i < mlist.size(); ++i) { for (unsigned int i = 0; i < mlist.size(); ++i) {
const QString currentMaster = QString::fromStdString(mlist[i].name); const QString currentMaster = QString::fromStdString(mlist[i].name);
availableMasters.append(currentMaster); availableMasters.append(currentMaster);
const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); const QList<QTableWidgetItem*> itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly);
if (itemList.isEmpty()) { // Master is not yet in the widget if (itemList.isEmpty()) { // Master is not yet in the widget
mMastersWidget->insertRow(i); mMastersWidget->insertRow(i);
QTableWidgetItem *item = new QTableWidgetItem(currentMaster); QTableWidgetItem *item = new QTableWidgetItem(currentMaster);
item->setForeground(Qt::red); item->setForeground(Qt::red);
item->setFlags(item->flags() & ~(Qt::ItemIsSelectable)); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
mMastersWidget->setItem(i, 0, item); mMastersWidget->setItem(i, 0, item);
}
} }
}
availableMasters.sort(); // Sort the masters alphabetically availableMasters.sort(); // Sort the masters alphabetically
// Now we put the current plugin in the mDataFilesModel under its masters // 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");
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;
std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; case 'B'://not Cell
if(select.type==ESM::VT_Int)
{
int isCell = int(toLower(actor.getCell()->cell->name) == toLower(name));
if(selectCompare<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)
{
if (isMatching (actor, *iter) && functionFilter(mActor,*iter,true))
{
if (!iter->sound.empty())
{
// TODO play sound
}
std::string text = iter->response;
parseText(text);
win->addText(iter->response);
executeScript(iter->resultScript);
greetingFound = true;
mLastTopic = it->first;
mLastDialogue = *iter;
break;
}
}
}
}
}
bool DialogueManager::compile (const std::string& cmd,std::vector<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());
}
std::cout << "response: " << iter->response << std::endl; return false;
}
if (!iter->sound.empty()) 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)
{ {
// TODO play sound if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
{
actorKnownTopics.push_back(it->first);
//does the player know the topic?
if(knownTopics.find(toLower(it->first)) != knownTopics.end())
{
keywordList.push_back(it->first);
break;
}
}
} }
}
}
win->setKeywords(keywordList);
mChoice = choice;
}
if (!iter->resultScript.empty()) void DialogueManager::keywordSelected(std::string keyword)
{
if(!mIsInChoice)
{
if(mDialogueMap.find(keyword) != mDialogueMap.end())
{
ESM::Dialogue ndialogue = mDialogueMap[keyword];
if(ndialogue.type == ESM::Dialogue::Topic)
{ {
std::cout << "script: " << iter->resultScript << std::endl; for (std::vector<ESM::DialInfo>::const_iterator iter = ndialogue.mInfo.begin();
// TODO execute script iter!=ndialogue.mInfo.end(); ++iter)
{
if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true))
{
std::string text = iter->response;
std::string script = iter->resultScript;
parseText(text);
MWGui::DialogueWindow* win = mEnvironment.mWindowManager->getDialogueWindow();
win->addTitle(keyword);
win->addText(iter->response);
executeScript(script);
mLastTopic = keyword;
mLastDialogue = *iter;
break;
}
}
} }
}
}
mEnvironment.mInputManager->setGuiMode(MWGui::GM_Dialogue); updateTopics();
break; }
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);
mEnvironment.mDialogueManager->keywordSelected(lower_string(topic));
}
//const std::string* theTopic = topicsList->getItemDataAt<std::string>(_index); void DialogueWindow::startDialogue(std::string npcName)
//std::cout << "Selected: "<< theTopic << std::endl; {
//eventTopicSelected(key); 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::updateOptions() 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)
{ {
//FIXME Add this properly for(unsigned int i = 0;i<topicsList->getItemCount();i++)
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"); std::string keyWord = topicsList->getItemNameAt(i);
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."); 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()
{
//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);
} }

@ -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)

@ -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 -->

@ -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>

@ -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…
Cancel
Save