diff --git a/CMakeLists.txt b/CMakeLists.txt index e11ad0c0ab..b83935bdcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,6 +370,10 @@ if(WIN32) INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" "${OpenMW_SOURCE_DIR}/readme.txt" + "${OpenMW_SOURCE_DIR}/GPL3.txt" + "${OpenMW_SOURCE_DIR}/OFL.txt" + "${OpenMW_SOURCE_DIR}/Bitstream Vera License.txt" + "${OpenMW_SOURCE_DIR}/Daedric Font License.txt" "${OpenMW_BINARY_DIR}/launcher.qss" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" @@ -391,8 +395,8 @@ if(WIN32) !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\" ") + SET(CPACK_RESOURCE_FILE_README "${OpenMW_SOURCE_DIR}/readme.txt") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt") - SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt") SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") SET(CPACK_NSIS_DISPLAY_NAME "OpenMW") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index ccefee1ee8..ed3559fdca 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -8,6 +8,7 @@ set(LAUNCHER playpage.cpp pluginsmodel.cpp pluginsview.cpp + filedialog.cpp launcher.rc ) @@ -22,6 +23,7 @@ set(LAUNCHER_HEADER playpage.hpp pluginsmodel.hpp pluginsview.hpp + filedialog.hpp ) # Headers that must be pre-processed @@ -34,6 +36,7 @@ set(LAUNCHER_HEADER_MOC playpage.hpp pluginsmodel.hpp pluginsview.hpp + filedialog.hpp ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index c15274e749..f3c5962cab 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -5,6 +5,7 @@ #include "datafilespage.hpp" #include "lineedit.hpp" +#include "filedialog.hpp" #include "naturalsort.hpp" #include "pluginsmodel.hpp" #include "pluginsview.hpp" @@ -203,8 +204,7 @@ void DataFilesPage::setupDataFiles() mCfgMgr.readConfiguration(variables, desc); // Put the paths in a boost::filesystem vector to use with Files::Collections - Files::PathContainer dataDirs(variables["data"].as()); - mDataDirs = dataDirs; + mDataDirs = Files::PathContainer(variables["data"].as()); // std::string local = variables["data-local"].as(); // if (!local.empty()) { @@ -212,36 +212,42 @@ void DataFilesPage::setupDataFiles() // dataDirs.push_back(Files::PathContainer::value_type(local)); // } - if (dataDirs.size()>1) - dataDirs.resize (1); + if (mDataDirs.size()>1) + mDataDirs.resize (1); - mCfgMgr.processPaths(dataDirs); - - while (dataDirs.empty()) { - // No valid data files directory found + mCfgMgr.processPaths(mDataDirs); + while (mDataDirs.empty()) { QMessageBox msgBox; msgBox.setWindowTitle("Error detecting Morrowind installation"); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Cancel); msgBox.setText(tr("
Could not find the Data Files location

\ - The directory containing the data files was not found.

\ - Press \"Browse...\" to specify the location manually.
")); + The directory containing the data files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); QAbstractButton *dirSelectButton = - msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); + msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); msgBox.exec(); if (msgBox.clickedButton() == dirSelectButton) { - QString dataDir = QFileDialog::getExistingDirectory( - this, tr("Select Data Files Directory"), - "/home", - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + // Show a custom dir selection dialog which only accepts valid dirs + QString selectedDir = FileDialog::getExistingDirectory( + this, tr("Select Data Files Directory"), + QDir::currentPath(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + // Add the user selected data directory + if (!selectedDir.isEmpty()) { + mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString())); + mCfgMgr.processPaths(mDataDirs); + } else { + // Cancel from within the dir selection dialog + break; + } - dataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); - mDataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); } else { // Cancel break; @@ -249,13 +255,13 @@ void DataFilesPage::setupDataFiles() } // Check if cancel was clicked because we can't exit from while loop - if (dataDirs.empty()) { + if (mDataDirs.empty()) { QApplication::exit(1); return; } - // Create a file collection for the dataDirs - Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as()); + // Create a file collection for the data dirs + Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as()); // First we add all the master files const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); @@ -1057,8 +1063,25 @@ void DataFilesPage::writeConfig(QString profile) return; } + QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); + QDir userPath(pathStr); + + if (!userPath.exists()) { + if (!userPath.mkpath(pathStr)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not create %0

\ + Please make sure you have the right permissions and try again.
").arg(pathStr)); + msgBox.exec(); + + qApp->exit(1); + return; + } + } // Open the OpenMW config as a QFile - QFile file(QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string())); + QFile file(pathStr.append("openmw.cfg")); if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { // File cannot be opened or created @@ -1067,7 +1090,7 @@ void DataFilesPage::writeConfig(QString profile) msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); + Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); qApp->exit(1); @@ -1098,7 +1121,7 @@ void DataFilesPage::writeConfig(QString profile) msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not write to %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); + Please make sure you have the right permissions and try again.
").arg(file.fileName())); msgBox.exec(); qApp->exit(1); diff --git a/apps/launcher/filedialog.cpp b/apps/launcher/filedialog.cpp new file mode 100644 index 0000000000..595501b919 --- /dev/null +++ b/apps/launcher/filedialog.cpp @@ -0,0 +1,57 @@ +#include "filedialog.hpp" +#include +#include + +FileDialog::FileDialog(QWidget *parent) + : QFileDialog(parent) +{ + // Remove the default Choose button to prevent it being updated elsewhere + QDialogButtonBox *box = qFindChild(this); + Q_ASSERT(box); + box->removeButton(box->button(QDialogButtonBox::Open)); + + // Add our own button so we can disable/enable it + mChooseButton = new QPushButton(tr("&Choose")); + mChooseButton->setIcon(QIcon::fromTheme("document-open")); + mChooseButton->setEnabled(false); + box->addButton(mChooseButton, QDialogButtonBox::AcceptRole); + + connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&))); + emit directoryEntered(QDir::currentPath()); +} + +QString FileDialog::getExistingDirectory(QWidget *parent, + const QString &caption, + const QString &dir, + Options options) +{ + // create a non-native file dialog + FileDialog dialog; + dialog.setFileMode(DirectoryOnly); + dialog.setOptions(options & (DontUseNativeDialog | ShowDirsOnly)); + + if (!caption.isEmpty()) + dialog.setWindowTitle(caption); + + if (!dir.isEmpty()) + dialog.setDirectory(dir); + + if (dialog.exec() == QDialog::Accepted) { + return dialog.selectedFiles().value(0); + } + return QString(); +} + +void FileDialog::updateChooseButton(const QString &directory) +{ + QDir currentDir = QDir(directory); + currentDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + currentDir.setNameFilters(QStringList() << "*.esm" << "*.esp"); + + if (!currentDir.entryList().isEmpty()) { + // There are data files in the current dir + mChooseButton->setEnabled(true); + } else { + mChooseButton->setEnabled(false); + } +} diff --git a/apps/launcher/filedialog.hpp b/apps/launcher/filedialog.hpp new file mode 100644 index 0000000000..7a161ecb96 --- /dev/null +++ b/apps/launcher/filedialog.hpp @@ -0,0 +1,28 @@ +#ifndef FILEDIALOG_HPP +#define FILEDIALOG_HPP + +#include + +class QPushButton; + +class FileDialog : public QFileDialog +{ + Q_OBJECT + +public: + FileDialog(QWidget *parent = 0); + + static QString getExistingDirectory(QWidget *parent = 0, + const QString &caption = QString(), + const QString &dir = QString(), + Options options = ShowDirsOnly); + +private slots: + void updateChooseButton(const QString &directory); + +private: + QPushButton *mChooseButton; +}; + + +#endif // FILEDIALOG_HPP diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index e156e4fbc2..22a9ca5bec 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -200,12 +200,13 @@ void GraphicsPage::writeConfig() Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); + Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString()); - std::string resolution = mResolutionComboBox->currentText().toStdString(); // parse resolution x and y from a string like "800 x 600" - size_t xPos = resolution.find("x"); - int resX = boost::lexical_cast(resolution.substr(0, xPos-1)); - int resY = boost::lexical_cast(resolution.substr(xPos+2, resolution.size()-(xPos+2))); + QString resolution = mResolutionComboBox->currentText(); + QStringList tokens = resolution.split(" ", QString::SkipEmptyParts); + int resX = boost::lexical_cast(tokens.at(0).toStdString()); + int resY = boost::lexical_cast(tokens.at(2).toStdString()); Settings::Manager::setInt("resolution x", "Video", resX); Settings::Manager::setInt("resolution y", "Video", resY); } @@ -239,6 +240,42 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy return result; } +QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) +{ + QString key ("Video Mode"); + QStringList result; + + uint row = 0; + Ogre::ConfigOptionMap options = renderer->getConfigOptions(); + + for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++) + { + if (key.toStdString() != i->first) + continue; + + Ogre::StringVector::iterator opt_it; + uint idx = 0; + for (opt_it = i->second.possibleValues.begin (); + opt_it != i->second.possibleValues.end (); opt_it++, idx++) + { + QString qval = QString::fromStdString(*opt_it).simplified(); + // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) + QStringList tokens = qval.split(" ", QString::SkipEmptyParts); + assert (tokens.size() >= 3); + QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); + { + + // do not add duplicate resolutions + if (!result.contains(resolutionStr)) + result << resolutionStr; + } + } + + } + + return result; +} + void GraphicsPage::rendererChanged(const QString &renderer) { mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); @@ -247,5 +284,5 @@ void GraphicsPage::rendererChanged(const QString &renderer) mResolutionComboBox->clear(); mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem)); + mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 1b0c6f388c..c2701f3625 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -59,6 +59,7 @@ private: Files::ConfigurationManager &mCfgMgr; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); + QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); void createPages(); void setupConfig(); diff --git a/apps/launcher/lineedit.cpp b/apps/launcher/lineedit.cpp index 254c09fce3..dac1964258 100644 --- a/apps/launcher/lineedit.cpp +++ b/apps/launcher/lineedit.cpp @@ -1,12 +1,3 @@ -/**************************************************************************** -** -** Copyright (c) 2007 Trolltech ASA -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - #include "lineedit.hpp" #include #include @@ -14,33 +5,33 @@ LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { - clearButton = new QToolButton(this); + mClearButton = new QToolButton(this); QPixmap pixmap(":images/clear.png"); - clearButton->setIcon(QIcon(pixmap)); - clearButton->setIconSize(pixmap.size()); - clearButton->setCursor(Qt::ArrowCursor); - clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); - clearButton->hide(); - connect(clearButton, SIGNAL(clicked()), this, SLOT(clear())); + mClearButton->setIcon(QIcon(pixmap)); + mClearButton->setIconSize(pixmap.size()); + mClearButton->setCursor(Qt::ArrowCursor); + mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + mClearButton->hide(); + connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); + setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); - setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), - qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); + setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2), + qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2)); } void LineEdit::resizeEvent(QResizeEvent *) { - QSize sz = clearButton->sizeHint(); + QSize sz = mClearButton->sizeHint(); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - clearButton->move(rect().right() - frameWidth - sz.width(), + mClearButton->move(rect().right() - frameWidth - sz.width(), (rect().bottom() + 1 - sz.height())/2); } void LineEdit::updateCloseButton(const QString& text) { - clearButton->setVisible(!text.isEmpty()); + mClearButton->setVisible(!text.isEmpty()); } diff --git a/apps/launcher/lineedit.hpp b/apps/launcher/lineedit.hpp index 7a96a523c8..2ed76d6eb7 100644 --- a/apps/launcher/lineedit.hpp +++ b/apps/launcher/lineedit.hpp @@ -28,7 +28,7 @@ private slots: void updateCloseButton(const QString &text); private: - QToolButton *clearButton; + QToolButton *mClearButton; }; #endif // LIENEDIT_H diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index bd29e2bcac..cbc1c4da36 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -31,8 +31,10 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - MainDialog dialog; - return dialog.exec(); + MainDialog mainWin; + mainWin.show(); + + return app.exec(); } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index d404fed8e7..63ea96b6f7 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -29,7 +29,10 @@ MainDialog::MainDialog() mSettings.loadUser(globaldefault); - mIconWidget = new QListWidget; + QWidget *centralWidget = new QWidget(this); + setCentralWidget(centralWidget); + + mIconWidget = new QListWidget(centralWidget); mIconWidget->setObjectName("IconWidget"); mIconWidget->setViewMode(QListView::IconMode); mIconWidget->setWrapping(false); @@ -43,7 +46,7 @@ MainDialog::MainDialog() mIconWidget->setCurrentRow(0); mIconWidget->setFlow(QListView::LeftToRight); - QGroupBox *groupBox = new QGroupBox(this); + QGroupBox *groupBox = new QGroupBox(centralWidget); QVBoxLayout *groupLayout = new QVBoxLayout(groupBox); mPagesWidget = new QStackedWidget(groupBox); @@ -51,16 +54,15 @@ MainDialog::MainDialog() QPushButton *playButton = new QPushButton(tr("Play")); - QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget); buttonBox->setStandardButtons(QDialogButtonBox::Close); buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); - QVBoxLayout *dialogLayout = new QVBoxLayout(this); + QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget); dialogLayout->addWidget(mIconWidget); dialogLayout->addWidget(groupBox); dialogLayout->addWidget(buttonBox); - setWindowTitle(tr("OpenMW Launcher")); setWindowIcon(QIcon(":/images/openmw.png")); // Remove what's this? button diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 0065aa8c47..59c6cbd2d4 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -1,7 +1,7 @@ #ifndef MAINDIALOG_H #define MAINDIALOG_H -#include +#include #include #include @@ -17,7 +17,7 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class MainDialog : public QDialog +class MainDialog : public QMainWindow { Q_OBJECT diff --git a/apps/launcher/resources/images/openmw-header.png b/apps/launcher/resources/images/openmw-header.png index a2ffab68b8..98c0cbe6fd 100644 Binary files a/apps/launcher/resources/images/openmw-header.png and b/apps/launcher/resources/images/openmw-header.png differ diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index e9b8ce31fc..99a32fc327 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -192,4 +192,17 @@ namespace MWClass { return getContainerStore (ptr).getWeight(); } + + void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const + { + if (lockLevel<0) + lockLevel = 0; + + ptr.getCellRef().lockLevel = lockLevel; + } + + void Container::unlock (const MWWorld::Ptr& ptr) const + { + ptr.getCellRef().lockLevel = 0; + } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 44f0fe927b..739c75c77c 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -44,6 +44,12 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; + ///< Lock object + + virtual void unlock (const MWWorld::Ptr& ptr) const; + ///< Unlock object + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e33fd322a7..c9b43896b2 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -57,6 +57,11 @@ namespace MWClass data->mCreatureStats.mLevel = ref->base->data.level; + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4c964c7007..f30e164f96 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -70,12 +70,12 @@ namespace MWClass } } + // creature stats if(ref->base->npdt52.gold != -10) { for (int i=0; i<27; ++i) data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]); - // creature stats data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength); data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence); data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower); @@ -95,6 +95,11 @@ namespace MWClass /// \todo do something with npdt12 maybe:p } + data->mCreatureStats.mHello = ref->base->AI.hello; + data->mCreatureStats.mFight = ref->base->AI.fight; + data->mCreatureStats.mFlee = ref->base->AI.flee; + data->mCreatureStats.mAlarm = ref->base->AI.alarm; + // store ptr.getRefData().setCustomData (data.release()); } diff --git a/apps/openmw/mwdialogue/dialoguemanager.cpp b/apps/openmw/mwdialogue/dialoguemanager.cpp index a19356d07f..45e2c8cb36 100644 --- a/apps/openmw/mwdialogue/dialoguemanager.cpp +++ b/apps/openmw/mwdialogue/dialoguemanager.cpp @@ -843,7 +843,7 @@ namespace MWDialogue void DialogueManager::goodbyeSelected() { - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); } void DialogueManager::questionAnswered(std::string answere) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index 9c26bfabe4..423678eed0 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -70,8 +70,8 @@ namespace MWGui void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.popGuiMode(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Alchemy); + mWindowManager.removeGuiMode(GM_Inventory); } void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index f1873b5508..a9dcd4555e 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -92,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Book); } void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -102,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mBook); take.execute(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Book); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 3f9a94e2db..c39e305dc9 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -708,6 +708,9 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) if (mGenerateClassResultDialog) mWM->removeDialog(mGenerateClassResultDialog); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); + const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(mGenerateClass); + mPlayerClass = *klass; + mWM->setPlayerClass(mPlayerClass); if (mCreationStage == CSE_ReviewNext) { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 6775fa6439..36ed16b0ef 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -640,7 +640,7 @@ void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) { if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } } @@ -671,7 +671,7 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) containerStore.clear(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } } diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 79b2d68bab..55bd49bebc 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -205,11 +205,14 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c std::string DialogueWindow::parseText(std::string text) { + bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored) for(unsigned int i = 0;igetItemCount();i++) { std::string keyWord = topicsList->getItemNameAt(i); - if (keyWord != "") + if (separatorReached && keyWord != "") addColorInString(text,keyWord,"#686EBA","#B29154"); + else + separatorReached = true; } return text; } diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 0bb7d3c1cf..ca04af8303 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -58,7 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; - mWindowManager->popGuiMode(); + mWindowManager->removeGuiMode(GM_InterMessageBox); } } @@ -86,13 +86,12 @@ void MessageBoxManager::createMessageBox (const std::string& message) bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector& buttons) { + /// \todo Don't write this kind of error message to cout. Either discard the old message box + /// silently or throw an exception. if(mInterMessageBoxe != NULL) { std::cout << "there is a MessageBox already" << std::endl; return false; } - std::cout << "interactive MessageBox: " << message << " - "; - std::copy (buttons.begin(), buttons.end(), std::ostream_iterator (std::cout, ", ")); - std::cout << std::endl; mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons); diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index f4d45fc265..92b18d953d 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -56,7 +56,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) { MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Scroll); } void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) @@ -66,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute(); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Scroll); } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 67ccf9d531..eafbd3462a 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -155,7 +155,7 @@ namespace MWGui void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Settings); } void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 47d299fdc6..a42da60d19 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -212,7 +212,7 @@ namespace MWGui std::string sound = "Item Gold Up"; MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Barter); } void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) @@ -222,7 +222,7 @@ namespace MWGui // now gimme back my stuff! mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr)); - mWindowManager.popGuiMode(); + mWindowManager.removeGuiMode(GM_Barter); } void TradeWindow::updateLabels() diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 5b963d3ae1..f62a3fa0f8 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -464,7 +464,7 @@ void WindowManager::onDialogueWindowBye() //removeDialog(dialogueWindow); mDialogueWindow->setVisible(false); } - popGuiMode(); + removeGuiMode(GM_Dialogue); } void WindowManager::onFrame (float frameDuration) @@ -677,6 +677,9 @@ void WindowManager::removeGuiMode(GuiMode mode) ++it; } + bool gameMode = !isGuiMode(); + MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); + updateVisible(); } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index cc3c409da2..8d40e19423 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -19,6 +19,10 @@ namespace MWMechanics Spells mSpells; ActiveSpells mActiveSpells; MagicEffects mMagicEffects; + int mHello; + int mFight; + int mFlee; + int mAlarm; }; } diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index aa541e55d3..08b1f6f8cf 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -7,6 +7,8 @@ #include #include +#include "../mwmechanics/creaturestats.hpp" + #include "interpretercontext.hpp" #include "ref.hpp" @@ -88,6 +90,95 @@ namespace MWScript } }; + template + class OpAiWander : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + +// Interpreter::Type_Float range = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float duration = runtime[0].mFloat; + runtime.pop(); + +// Interpreter::Type_Float time = runtime[0].mFloat; + runtime.pop(); + + // discard additional idle arguments for now + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i + class OpSetHello : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mHello = value; + } + }; + + template + class OpSetFight : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFight = value; + } + }; + + template + class OpSetFlee : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mFlee = value; + } + }; + + template + class OpSetAlarm : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Class::get (ptr).getCreatureStats (ptr).mAlarm = value; + } + }; const int opcodeAiTravel = 0x20000; @@ -96,6 +187,16 @@ namespace MWScript const int opcodeAiEscortExplicit = 0x20003; const int opcodeGetAiPackageDone = 0x200007c; const int opcodeGetAiPackageDoneExplicit = 0x200007d; + const int opcodeAiWander = 0x20010; + const int opcodeAiWanderExplicit = 0x20011; + const int opcodeSetHello = 0x200015e; + const int opcodeSetHelloExplicit = 0x200015d; + const int opcodeSetFight = 0x200015e; + const int opcodeSetFightExplicit = 0x200015f; + const int opcodeSetFlee = 0x2000160; + const int opcodeSetFleeExplicit = 0x2000161; + const int opcodeSetAlarm = 0x2000162; + const int opcodeSetAlarmExplicit = 0x2000163; void registerExtensions (Compiler::Extensions& extensions) { @@ -103,9 +204,16 @@ namespace MWScript opcodeAiTravelExplicit); extensions.registerInstruction ("aiescort", "cffff/l", opcodeAiEscort, opcodeAiEscortExplicit); + extensions.registerInstruction ("aiwander", "fff/llllllllll", opcodeAiWander, + opcodeAiWanderExplicit); extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone, opcodeGetAiPackageDoneExplicit); + + extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit); + extensions.registerInstruction ("setfight", "l", opcodeSetFight, opcodeSetFightExplicit); + extensions.registerInstruction ("setflee", "l", opcodeSetFlee, opcodeSetFleeExplicit); + extensions.registerInstruction ("setalarm", "l", opcodeSetAlarm, opcodeSetAlarmExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -114,9 +222,19 @@ namespace MWScript interpreter.installSegment3 (opcodeAiTravelExplicit, new OpAiTravel); interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort); interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscort); + interpreter.installSegment3 (opcodeAiWander, new OpAiWander); + interpreter.installSegment3 (opcodeAiWanderExplicit, new OpAiWander); interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); + interpreter.installSegment5 (opcodeSetHello, new OpSetHello); + interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello); + interpreter.installSegment5 (opcodeSetFight, new OpSetFight); + interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetFight); + interpreter.installSegment5 (opcodeSetFlee, new OpSetFlee); + interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetFlee); + interpreter.installSegment5 (opcodeSetAlarm, new OpSetAlarm); + interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAlarm); } } } diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 078d0da5e7..0a6ffd0c7a 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -5,6 +5,8 @@ #include "../mwworld/world.hpp" +#include "scriptmanager.hpp" + namespace MWScript { CompilerContext::CompilerContext (Type type) @@ -21,6 +23,18 @@ namespace MWScript return MWBase::Environment::get().getWorld()->getGlobalVariableType (name); } + char CompilerContext::getMemberType (const std::string& name, const std::string& id) const + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (script.empty()) + return ' '; + + return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name); + } + bool CompilerContext::isId (const std::string& name) const { return diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index 32b2f1881c..5ec98e09a7 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -30,6 +30,9 @@ namespace MWScript /// 'l: long, 's': short, 'f': float, ' ': does not exist. virtual char getGlobalType (const std::string& name) const; + virtual char getMemberType (const std::string& name, const std::string& id) const; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + virtual bool isId (const std::string& name) const; ///< Does \a name match an ID, that can be referenced? }; diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 363a09b6bd..1a7b452465 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -11,7 +11,10 @@ #include "../mwworld/player.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "interpretercontext.hpp" +#include "ref.hpp" #include @@ -54,11 +57,71 @@ namespace MWScript } }; + template + class OpClearForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = false; + } + }; + + template + class OpForceRun : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceRun = true; + } + }; + + template + class OpClearForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = false; + } + }; + + template + class OpForceSneak : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWWorld::Class::get (ptr).getNpcStats (ptr).mForceSneak = true; + } + }; + const int numberOfControls = 7; const int opcodeEnable = 0x200007e; const int opcodeDisable = 0x2000085; const int opcodeToggleCollision = 0x2000130; + const int opcodeClearForceRun = 0x2000154; + const int opcodeClearForceRunExplicit = 0x2000155; + const int opcodeForceRun = 0x2000156; + const int opcodeForceRunExplicit = 0x2000157; + const int opcodeClearForceSneak = 0x2000158; + const int opcodeClearForceSneakExplicit = 0x2000159; + const int opcodeForceSneak = 0x200015a; + const int opcodeForceSneakExplicit = 0x200015b; const char *controls[numberOfControls] = { @@ -79,6 +142,16 @@ namespace MWScript extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision); extensions.registerInstruction ("tcl", "", opcodeToggleCollision); + + extensions.registerInstruction ("clearforcerun", "", opcodeClearForceRun, + opcodeClearForceRunExplicit); + extensions.registerInstruction ("forcerun", "", opcodeForceRun, + opcodeForceRunExplicit); + + extensions.registerInstruction ("clearforcesneak", "", opcodeClearForceSneak, + opcodeClearForceSneakExplicit); + extensions.registerInstruction ("forcesneak", "", opcodeForceSneak, + opcodeForceSneakExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -90,6 +163,20 @@ namespace MWScript } interpreter.installSegment5 (opcodeToggleCollision, new OpToggleCollision); + + interpreter.installSegment5 (opcodeClearForceRun, new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRun, new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneak, new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneak, new OpForceSneak); + + interpreter.installSegment5 (opcodeClearForceRunExplicit, + new OpClearForceRun); + interpreter.installSegment5 (opcodeForceRunExplicit, + new OpForceRun); + interpreter.installSegment5 (opcodeClearForceSneakExplicit, + new OpClearForceSneak); + interpreter.installSegment5 (opcodeForceSneakExplicit, + new OpForceSneak); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 4423f17cfb..8a166eff3a 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -29,7 +29,9 @@ op 0x2000c: PCLowerRank op 0x2000d: PCJoinFaction op 0x2000e: PCGetRank implicit op 0x2000f: PCGetRank explicit -opcodes 0x20010-0x3ffff unused +op 0x20010: AiWander +op 0x20011: AiWander, explicit reference +opcodes 0x20012-0x3ffff unused Segment 4: (not implemented yet) @@ -147,4 +149,20 @@ op 0x2000150: ForceGreeting, explicit reference op 0x2000151: ToggleFullHelp op 0x2000152: Goodbye op 0x2000153: DontSaveObject (left unimplemented) -opcodes 0x2000154-0x3ffffff unused +op 0x2000154: ClearForceRun +op 0x2000155: ClearForceRun, explicit reference +op 0x2000156: ForceRun +op 0x2000157: ForceRun, explicit reference +op 0x2000158: ClearForceSneak +op 0x2000159: ClearForceSneak, explicit reference +op 0x200015a: ForceSneak +op 0x200015b: ForceSneak, explicit reference +op 0x200015c: SetHello +op 0x200015d: SetHello, explicit reference +op 0x200015e: SetFight +op 0x200015f: SetFight, explicit reference +op 0x2000160: SetFlee +op 0x2000161: SetFlee, explicit reference +op 0x2000162: SetAlarm +op 0x2000163: SetAlarm, explicit reference +opcodes 0x2000164-0x3ffffff unused diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index b267cc6e49..8e5897298b 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -104,7 +104,7 @@ namespace MWScript extensions.registerInstruction ("enableclassmenu", "", opcodeEnableClassMenu); extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu); extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu); - extensions.registerInstruction ("enablestatsreviewmenu", "", + extensions.registerInstruction ("enablestatreviewmenu", "", opcodeEnableStatsReviewMenu); extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu); diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index a369486faf..152fcf85cb 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -270,6 +270,84 @@ namespace MWScript MWBase::Environment::get().getWorld()->disable (ref); } + int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + return ptr.getRefData().getLocals().mShorts[index]; + } + + int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + return ptr.getRefData().getLocals().mLongs[index]; + } + + float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + return ptr.getRefData().getLocals().mFloats[index]; + } + + void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + ptr.getRefData().getLocals().mShorts[index] = value; + } + + void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + ptr.getRefData().getLocals().mLongs[index] = value; + } + + void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value) + { + const MWWorld::Ptr ptr = getReference (id, false); + + std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr); + + int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f'); + + ptr.getRefData().setLocals ( + *MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId)); + ptr.getRefData().getLocals().mFloats[index] = value; + } + MWWorld::Ptr InterpreterContext::getReference() { return getReference ("", true); diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 40f53337db..9fdc3c21a0 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -107,6 +107,18 @@ namespace MWScript virtual void disable (const std::string& id = ""); + virtual int getMemberShort (const std::string& id, const std::string& name) const; + + virtual int getMemberLong (const std::string& id, const std::string& name) const; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value); + + virtual void setMemberLong (const std::string& id, const std::string& name, int value); + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value); + MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; diff --git a/apps/openmw/mwscript/scriptmanager.cpp b/apps/openmw/mwscript/scriptmanager.cpp index 506cf049c4..d8bd269c69 100644 --- a/apps/openmw/mwscript/scriptmanager.cpp +++ b/apps/openmw/mwscript/scriptmanager.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "extensions.hpp" @@ -46,8 +47,14 @@ namespace MWScript if (!mErrorHandler.isGood()) Success = false; } - catch (...) + catch (const Compiler::SourceException&) { + // error has already been reported via error handler + Success = false; + } + catch (const std::exception& error) + { + std::cerr << "An exception has been thrown: " << error.what() << std::endl; Success = false; } @@ -140,6 +147,9 @@ namespace MWScript { if (!compile (name)) { + /// \todo Handle case of cyclic member variable access. Currently this could look up + /// the whole application in an endless recursion. + // failed -> ignore script from now on. std::vector empty; mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); @@ -156,4 +166,43 @@ namespace MWScript { return mGlobalScripts; } + + int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable, + char type) + { + const ESM::Script *script = mStore.scripts.find (scriptId); + + int offset = 0; + int size = 0; + + switch (type) + { + case 's': + + offset = 0; + size = script->data.numShorts; + break; + + case 'l': + + offset = script->data.numShorts; + size = script->data.numLongs; + break; + + case 'f': + + offset = script->data.numShorts+script->data.numLongs; + size = script->data.numFloats; + + default: + + throw std::runtime_error ("invalid variable type"); + } + + for (int i=0; ivarNames.at (i+offset)==variable) + return i; + + throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId); + } } diff --git a/apps/openmw/mwscript/scriptmanager.hpp b/apps/openmw/mwscript/scriptmanager.hpp index 35c1fadd9e..34cc0defec 100644 --- a/apps/openmw/mwscript/scriptmanager.hpp +++ b/apps/openmw/mwscript/scriptmanager.hpp @@ -67,6 +67,10 @@ namespace MWScript ///< Return locals for script \a name. GlobalScripts& getGlobalScripts(); + + int getLocalIndex (const std::string& scriptId, const std::string& variable, char type); + ///< Return index of the variable of the given name and type in the given script. Will + /// throw an exception, if there is no such script or variable or the type does not match. }; }; diff --git a/apps/openmw/mwsound/audiere_decoder.cpp b/apps/openmw/mwsound/audiere_decoder.cpp index acc2e5283c..4e73573a74 100644 --- a/apps/openmw/mwsound/audiere_decoder.cpp +++ b/apps/openmw/mwsound/audiere_decoder.cpp @@ -41,8 +41,8 @@ class OgreFile : public audiere::File } size_t refs; - virtual void ref() { ++refs; } - virtual void unref() + ADR_METHOD(void) ref() { ++refs; } + ADR_METHOD(void) unref() { if(--refs == 0) delete this; diff --git a/apps/openmw/mwworld/actionalchemy.cpp b/apps/openmw/mwworld/actionalchemy.cpp index a2f3bd1e4e..eb91b6946d 100644 --- a/apps/openmw/mwworld/actionalchemy.cpp +++ b/apps/openmw/mwworld/actionalchemy.cpp @@ -7,7 +7,6 @@ namespace MWWorld { void ActionAlchemy::execute() { - MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy); } } diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index b6d3e38ce7..990a4cc4a3 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -142,7 +142,10 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce (int(*)(int)) std::tolower); if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase)) + { cell.load (mStore, mReader); + fillContainers (cell); + } else return Ptr(); } diff --git a/cmake/FindBullet.cmake b/cmake/FindBullet.cmake index 552a0651af..8d5ea2f1e5 100644 --- a/cmake/FindBullet.cmake +++ b/cmake/FindBullet.cmake @@ -19,6 +19,8 @@ # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. +set(BULLET_ROOT $ENV{BULLET_ROOT}) + macro(_FIND_BULLET_LIBRARY _var) find_library(${_var} NAMES diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index c79ee5998c..7278fe2007 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -22,7 +22,7 @@ IF (WIN32) #Windows SET(MYGUISDK $ENV{MYGUI_HOME}) IF (MYGUISDK) findpkg_begin ( "MYGUI" ) - MESSAGE(STATUS "Using MyGUI in OGRE SDK") + MESSAGE(STATUS "Using MyGUI in MyGUI SDK") STRING(REGEX REPLACE "[\\]" "/" MYGUISDK "${MYGUISDK}" ) find_path ( MYGUI_INCLUDE_DIRS @@ -35,7 +35,7 @@ MyGUI_OgrePlatform.h "${MYGUISDK}/Platforms/Ogre/OgrePlatform/include" NO_DEFAULT_PATH ) -SET ( MYGUI_LIB_DIR ${MYGUISDK}/*/lib ) +SET ( MYGUI_LIB_DIR ${MYGUISDK}/lib ${MYGUISDK}/*/lib ) find_library ( MYGUI_LIBRARIES_REL NAMES MyGUIEngine.lib @@ -69,7 +69,7 @@ make_library_set ( MYGUI_PLATFORM_LIBRARIES ) MESSAGE ("${MYGUI_LIBRARIES}") MESSAGE ("${MYGUI_PLATFORM_LIBRARIES}") -findpkg_finish ( "MYGUI" ) +#findpkg_finish ( "MYGUI" ) ENDIF (MYGUISDK) IF (OGRESOURCE) diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index 929119cf40..1b02613c59 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -10,33 +10,35 @@ namespace Compiler class Context { const Extensions *mExtensions; - + public: - + Context() : mExtensions (0) {} - + virtual ~Context() {} - + virtual bool canDeclareLocals() const = 0; ///< Is the compiler allowed to declare local variables? - + void setExtensions (const Extensions *extensions = 0) { mExtensions = extensions; } - + const Extensions *getExtensions() const { return mExtensions; } - + virtual char getGlobalType (const std::string& name) const = 0; ///< 'l: long, 's': short, 'f': float, ' ': does not exist. - + + virtual char getMemberType (const std::string& name, const std::string& id) const = 0; + ///< 'l: long, 's': short, 'f': float, ' ': does not exist. + virtual bool isId (const std::string& name) const = 0; ///< Does \a name match an ID, that can be referenced? }; } #endif - diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 95480c0239..52192625b1 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -195,10 +195,31 @@ namespace Compiler return parseArguments (arguments, scanner, mCode); } + bool ExprParser::handleMemberAccess (const std::string& name) + { + mMemberOp = false; + + std::string name2 = toLower (name); + std::string id = toLower (mExplicit); + + char type = getContext().getMemberType (name2, id); + + if (type!=' ') + { + Generator::fetchMember (mCode, mLiterals, type, name2, id); + mNextOperand = false; + mExplicit.clear(); + mOperands.push_back (type=='f' ? 'f' : 'l'); + return true; + } + + return false; + } + ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals, bool argument) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), - mNextOperand (true), mFirst (true), mArgument (argument) + mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false) {} bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) @@ -251,7 +272,12 @@ namespace Compiler Scanner& scanner) { if (!mExplicit.empty()) + { + if (mMemberOp && handleMemberAccess (name)) + return true; + return Parser::parseName (name, loc, scanner); + } mFirst = false; @@ -281,9 +307,9 @@ namespace Compiler return true; } - if (mExplicit.empty() && getContext().isId (name)) + if (mExplicit.empty() && getContext().isId (name2)) { - mExplicit = name; + mExplicit = name2; return true; } } @@ -497,6 +523,12 @@ namespace Compiler return true; } + if (!mMemberOp && code==Scanner::S_member) + { + mMemberOp = true; + return true; + } + return Parser::parseSpecial (code, loc, scanner); } @@ -609,6 +641,7 @@ namespace Compiler mFirst = true; mExplicit.clear(); mRefOp = false; + mMemberOp = false; Parser::reset(); } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 87945c6280..8ce5409d23 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -26,6 +26,7 @@ namespace Compiler bool mArgument; std::string mExplicit; bool mRefOp; + bool mMemberOp; int getPriority (char op) const; @@ -53,6 +54,8 @@ namespace Compiler int parseArguments (const std::string& arguments, Scanner& scanner); + bool handleMemberAccess (const std::string& name); + public: ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 26a80387b1..9b02e4273f 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -260,6 +260,36 @@ namespace code.push_back (Compiler::Generator::segment5 (44)); } + void opStoreMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (59)); + } + + void opStoreMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (60)); + } + + void opStoreMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (61)); + } + + void opFetchMemberShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (62)); + } + + void opFetchMemberLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (63)); + } + + void opFetchMemberFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (64)); + } + void opRandom (Compiler::Generator::CodeContainer& code) { code.push_back (Compiler::Generator::segment5 (45)); @@ -644,7 +674,7 @@ namespace Compiler if (localType!=valueType) { - if (localType=='f' && valueType=='l') + if (localType=='f' && (valueType=='l' || valueType=='s')) { opIntToFloat (code); } @@ -707,6 +737,88 @@ namespace Compiler } } + void assignToMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + opPushInt (code, index); + + std::copy (value.begin(), value.end(), std::back_inserter (code)); + + if (localType!=valueType) + { + if (localType=='f' && (valueType=='l' || valueType=='s')) + { + opIntToFloat (code); + } + else if ((localType=='l' || localType=='s') && valueType=='f') + { + opFloatToInt (code); + } + } + + switch (localType) + { + case 'f': + + opStoreMemberFloat (code); + break; + + case 's': + + opStoreMemberShort (code); + break; + + case 'l': + + opStoreMemberLong (code); + break; + + default: + + assert (0); + } + } + + void fetchMember (CodeContainer& code, Literals& literals, char localType, + const std::string& name, const std::string& id) + { + int index = literals.addString (name); + + opPushInt (code, index); + + index = literals.addString (id); + + opPushInt (code, index); + + switch (localType) + { + case 'f': + + opFetchMemberFloat (code); + break; + + case 's': + + opFetchMemberShort (code); + break; + + case 'l': + + opFetchMemberLong (code); + break; + + default: + + assert (0); + } + } + void random (CodeContainer& code) { opRandom (code); diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 89e1984314..feab26c93d 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -101,6 +101,12 @@ namespace Compiler void fetchGlobal (CodeContainer& code, Literals& literals, char localType, const std::string& name); + void assignToMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id, const CodeContainer& value, char valueType); + + void fetchMember (CodeContainer& code, Literals& literals, char memberType, + const std::string& name, const std::string& id); + void random (CodeContainer& code); void scriptRunning (CodeContainer& code); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 834cd27b48..a4cbc1ffeb 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -18,7 +18,10 @@ namespace Compiler if (!mExplicit.empty()) { mExprParser.parseName (mExplicit, loc, scanner); - mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); + if (mState==MemberState) + mExprParser.parseSpecial (Scanner::S_member, loc, scanner); + else + mExprParser.parseSpecial (Scanner::S_ref, loc, scanner); } scanner.scan (mExprParser); @@ -110,12 +113,13 @@ namespace Compiler if (mState==SetState) { std::string name2 = toLower (name); + mName = name2; // local variable? char type = mLocals.getType (name2); if (type!=' ') { - mName = name2; + mType = type; mState = SetLocalVarState; return true; } @@ -123,12 +127,27 @@ namespace Compiler type = getContext().getGlobalType (name2); if (type!=' ') { - mName = name2; mType = type; mState = SetGlobalVarState; return true; } + mState = SetPotentialMemberVarState; + return true; + } + + if (mState==SetMemberVarState) + { + mMemberName = toLower (name); + char type = getContext().getMemberType (mMemberName, mName); + + if (type!=' ') + { + mState = SetMemberVarState2; + mType = type; + return true; + } + getErrorHandler().error ("unknown variable", loc); SkipParser skip (getErrorHandler(), getContext()); scanner.scan (skip); @@ -256,6 +275,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } @@ -269,6 +289,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -333,6 +354,19 @@ namespace Compiler mState = EndState; return true; } + else if (mState==SetMemberVarState2 && keyword==Scanner::K_to) + { + mExprParser.reset(); + scanner.scan (mExprParser); + + std::vector code; + char type = mExprParser.append (code); + + Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type); + + mState = EndState; + return true; + } if (mAllowExpression) { @@ -342,6 +376,7 @@ namespace Compiler { scanner.putbackKeyword (keyword, loc); parseExpression (scanner, loc); + mState = EndState; return true; } } @@ -366,6 +401,14 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==PotentialExplicitState) + { + mState = MemberState; + parseExpression (scanner, loc); + mState = EndState; + return true; + } + if (code==Scanner::S_newline && mState==MessageButtonState) { Generator::message (mCode, mLiterals, mName, mButtons); @@ -378,11 +421,18 @@ namespace Compiler return true; } + if (code==Scanner::S_member && mState==SetPotentialMemberVarState) + { + mState = SetMemberVarState; + return true; + } + if (mAllowExpression && mState==BeginState && (code==Scanner::S_open || code==Scanner::S_minus)) { scanner.putbackSpecial (code, loc); parseExpression (scanner, loc); + mState = EndState; return true; } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 531b7762f0..aa74cd232f 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -21,10 +21,11 @@ namespace Compiler { BeginState, ShortState, LongState, FloatState, - SetState, SetLocalVarState, SetGlobalVarState, + SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState, + SetMemberVarState, SetMemberVarState2, MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState, EndState, - PotentialExplicitState, ExplicitState + PotentialExplicitState, ExplicitState, MemberState }; Locals& mLocals; @@ -32,6 +33,7 @@ namespace Compiler std::vector& mCode; State mState; std::string mName; + std::string mMemberName; int mButtons; std::string mExplicit; char mType; diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index d0397e8cf1..962699dfa4 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -360,6 +360,8 @@ namespace Compiler special = S_open; else if (c==')') special = S_close; + else if (c=='.') + special = S_member; else if (c=='=') { if (get (c)) diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 53cb92ef26..19f4ca96ad 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -65,7 +65,8 @@ namespace Compiler S_cmpEQ, S_cmpNE, S_cmpLT, S_cmpLE, S_cmpGT, S_cmpGE, S_plus, S_minus, S_mult, S_div, S_comma, - S_ref + S_ref, + S_member }; private: diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 973b22d350..4221da36ed 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -65,6 +65,19 @@ namespace Interpreter virtual void enable (const std::string& id = "") = 0; virtual void disable (const std::string& id = "") = 0; + + virtual int getMemberShort (const std::string& id, const std::string& name) const = 0; + + virtual int getMemberLong (const std::string& id, const std::string& name) const = 0; + + virtual float getMemberFloat (const std::string& id, const std::string& name) const = 0; + + virtual void setMemberShort (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberLong (const std::string& id, const std::string& name, int value) = 0; + + virtual void setMemberFloat (const std::string& id, const std::string& name, float value) + = 0; }; } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 3e513aa44e..91e0c060e7 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -121,5 +121,11 @@ op 58: report string literal index in stack[0]; additional arguments (if any) in stack[n]..stack[1]; n is determined according to the message string all arguments are removed from stack -opcodes 59-33554431 unused +op 59: store stack[0] in member short stack[2] of object with ID stack[1] +op 60: store stack[0] in member long stack[2] of object with ID stack[1] +op 61: store stack[0] in member float stack[2] of object with ID stack[1] +op 62: replace stack[0] with member short stack[1] of object with ID stack[0] +op 63: replace stack[0] with member short stack[1] of object with ID stack[0] +op 64: replace stack[0] with member short stack[1] of object with ID stack[0] +opcodes 65-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index 556477af25..05f71f1cca 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -40,6 +40,12 @@ namespace Interpreter interpreter.installSegment5 (42, new OpFetchGlobalShort); interpreter.installSegment5 (43, new OpFetchGlobalLong); interpreter.installSegment5 (44, new OpFetchGlobalFloat); + interpreter.installSegment5 (59, new OpStoreMemberShort); + interpreter.installSegment5 (60, new OpStoreMemberLong); + interpreter.installSegment5 (61, new OpStoreMemberFloat); + interpreter.installSegment5 (62, new OpFetchMemberShort); + interpreter.installSegment5 (63, new OpFetchMemberLong); + interpreter.installSegment5 (64, new OpFetchMemberFloat); // math interpreter.installSegment5 (9, new OpAddInt); diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index ea62b7ad89..731c16276d 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -6,11 +6,11 @@ #include "context.hpp" namespace Interpreter -{ +{ class OpStoreLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -20,13 +20,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -36,13 +36,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -52,71 +52,71 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchIntLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger); runtime[0].mInteger = intValue; - } - }; - + } + }; + class OpFetchFloatLiteral : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger); runtime[0].mFloat = floatValue; - } - }; - + } + }; + class OpFetchLocalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; int value = runtime.getContext().getLocalShort (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; int value = runtime.getContext().getLocalLong (index); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchLocalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; float value = runtime.getContext().getLocalFloat (index); runtime[0].mFloat = value; - } - }; - + } + }; + class OpStoreGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -128,13 +128,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpStoreGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Integer data = runtime[0].mInteger; @@ -146,13 +146,13 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } - }; - + } + }; + class OpStoreGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { Type_Float data = runtime[0].mFloat; @@ -164,48 +164,158 @@ namespace Interpreter runtime.pop(); runtime.pop(); - } + } }; - + class OpFetchGlobalShort : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalShort (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalLong : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { - int index = runtime[0].mInteger; + int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Integer value = runtime.getContext().getGlobalLong (name); runtime[0].mInteger = value; - } - }; + } + }; class OpFetchGlobalFloat : public Opcode0 { public: - + virtual void execute (Runtime& runtime) { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); Type_Float value = runtime.getContext().getGlobalFloat (name); runtime[0].mFloat = value; - } - }; + } + }; + + class OpStoreMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberShort (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = runtime[0].mInteger; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberLong (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpStoreMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Float data = runtime[0].mFloat; + Type_Integer index = runtime[1].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[2].mInteger; + std::string variable = runtime.getStringLiteral (index); + + runtime.getContext().setMemberFloat (id, variable, data); + + runtime.pop(); + runtime.pop(); + runtime.pop(); + } + }; + + class OpFetchMemberShort : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + int value = runtime.getContext().getMemberShort (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberLong : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + int value = runtime.getContext().getMemberLong (id, variable); + runtime[0].mInteger = value; + } + }; + + class OpFetchMemberFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer index = runtime[0].mInteger; + std::string id = runtime.getStringLiteral (index); + index = runtime[1].mInteger; + std::string variable = runtime.getStringLiteral (index); + runtime.pop(); + + float value = runtime.getContext().getMemberFloat (id, variable); + runtime[0].mFloat = value; + } + }; } #endif - diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index a94434e5b5..1bc4341a09 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -222,6 +222,14 @@ namespace Physic PhysicEngine::~PhysicEngine() { + HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin(); + for (; hf_it != mHeightFieldMap.end(); ++hf_it) + { + dynamicsWorld->removeRigidBody(hf_it->second.mBody); + delete hf_it->second.mShape; + delete hf_it->second.mBody; + } + RigidBodyContainer::iterator rb_it = RigidBodyMap.begin(); for (; rb_it != RigidBodyMap.end(); ++rb_it) { @@ -320,6 +328,8 @@ namespace Physic dynamicsWorld->removeRigidBody(hf.mBody); delete hf.mShape; delete hf.mBody; + + mHeightFieldMap.erase(name); } RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) @@ -478,7 +488,7 @@ namespace Physic dynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { - name = static_cast(*resultCallback1.m_collisionObject).mName; + name = static_cast(*resultCallback1.m_collisionObject).mName; d1 = resultCallback1.m_closestHitFraction; d = d1; } @@ -492,7 +502,7 @@ namespace Physic d2 = resultCallback1.m_closestHitFraction; if(d2<=d1) { - name = static_cast(*resultCallback2.m_collisionObject).mName; + name = static_cast(*resultCallback2.m_collisionObject).mName; d = d2; } } @@ -505,25 +515,25 @@ namespace Physic MyRayResultCallback resultCallback1; resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; dynamicsWorld->rayTest(from, to, resultCallback1); - std::vector< std::pair > results = resultCallback1.results; + std::vector< std::pair > results = resultCallback1.results; MyRayResultCallback resultCallback2; resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; dynamicsWorld->rayTest(from, to, resultCallback2); - std::vector< std::pair > actorResults = resultCallback2.results; + std::vector< std::pair > actorResults = resultCallback2.results; std::vector< std::pair > results2; - for (std::vector< std::pair >::iterator it=results.begin(); + for (std::vector< std::pair >::iterator it=results.begin(); it != results.end(); ++it) { - results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); } - for (std::vector< std::pair >::iterator it=actorResults.begin(); + for (std::vector< std::pair >::iterator it=actorResults.begin(); it != actorResults.end(); ++it) { - results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); } std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8115723201..e327f24e15 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -278,7 +278,7 @@ namespace Physic return false; } - std::vector < std::pair > results; + std::vector < std::pair > results; }; }} diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp index 591f1869f8..b723f67e47 100644 --- a/libs/openengine/bullet/pmove.cpp +++ b/libs/openengine/bullet/pmove.cpp @@ -15,8 +15,6 @@ Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc. //#include "GameTime.h" -//#include "Object.h" - //#include "Sound.h" //#include "..\..\ESMParser\ESMParser\SNDG.h" @@ -68,7 +66,6 @@ static struct playermoveLocal int waterHeight; bool hasWater; bool isInterior; - //Object* traceObj; } pml; @@ -1833,13 +1830,6 @@ void PmoveSingle (playerMove* const pmove) pml.hasWater = pmove->hasWater; pml.isInterior = pmove->isInterior; pml.waterHeight = pmove->waterHeight; -#ifdef _DEBUG - if (!pml.traceObj) - __debugbreak(); - - if (!pml.traceObj->incellptr) - __debugbreak(); -#endif // determine the time pml.msec = pmove->cmd.serverTime - pm->ps.commandTime; diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h index e46eb9d2e7..6cedd35995 100644 --- a/libs/openengine/bullet/pmove.h +++ b/libs/openengine/bullet/pmove.h @@ -190,7 +190,6 @@ struct playerMove int waterHeight; bool hasWater; bool isInterior; - //Object* traceObj; OEngine::Physic::PhysicEngine* mEngine; }; diff --git a/readme.txt b/readme.txt index 513474dd64..4cc31343b0 100644 --- a/readme.txt +++ b/readme.txt @@ -110,6 +110,7 @@ Nikolay “corristo” Kasyanov Pieter “pvdk” van der Kloet Roman "Kromgart" Melnik Sebastian “swick” Wick +Sylvain "Garvek" T. Retired Developers: Ardekantur