1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-24 00:23:53 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jason Hooks 2012-06-20 23:52:31 -04:00
commit 71c3bd6288
62 changed files with 1104 additions and 182 deletions

View file

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

View file

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

View file

@ -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<Files::PathContainer>());
mDataDirs = dataDirs;
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
// std::string local = variables["data-local"].as<std::string>();
// 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("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
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<bool>());
// Create a file collection for the data dirs
Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as<bool>());
// 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("<br><b>Could not create %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").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("<br><b>Could not open or create %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
Please make sure you have the right permissions and try again.<br>").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("<br><b>Could not write to %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
msgBox.exec();
qApp->exit(1);

View file

@ -0,0 +1,57 @@
#include "filedialog.hpp"
#include <QDialogButtonBox>
#include <QPushButton>
FileDialog::FileDialog(QWidget *parent)
: QFileDialog(parent)
{
// Remove the default Choose button to prevent it being updated elsewhere
QDialogButtonBox *box = qFindChild<QDialogButtonBox*>(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);
}
}

View file

@ -0,0 +1,28 @@
#ifndef FILEDIALOG_HPP
#define FILEDIALOG_HPP
#include <QFileDialog>
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

View file

@ -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<int>(resolution.substr(0, xPos-1));
int resY = boost::lexical_cast<int>(resolution.substr(xPos+2, resolution.size()-(xPos+2)));
QString resolution = mResolutionComboBox->currentText();
QStringList tokens = resolution.split(" ", QString::SkipEmptyParts);
int resX = boost::lexical_cast<int>(tokens.at(0).toStdString());
int resY = boost::lexical_cast<int>(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));
}

View file

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

View file

@ -1,12 +1,3 @@
/****************************************************************************
**
** Copyright (c) 2007 Trolltech ASA <info@trolltech.com>
**
** Use, modification and distribution is allowed without limitation,
** warranty, liability or support of any kind.
**
****************************************************************************/
#include "lineedit.hpp"
#include <QToolButton>
#include <QStyle>
@ -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());
}

View file

@ -28,7 +28,7 @@ private slots:
void updateCloseButton(const QString &text);
private:
QToolButton *clearButton;
QToolButton *mClearButton;
};
#endif // LIENEDIT_H

View file

@ -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();
}

View file

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

View file

@ -1,7 +1,7 @@
#ifndef MAINDIALOG_H
#define MAINDIALOG_H
#include <QDialog>
#include <QMainWindow>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
@ -17,7 +17,7 @@ class PlayPage;
class GraphicsPage;
class DataFilesPage;
class MainDialog : public QDialog
class MainDialog : public QMainWindow
{
Q_OBJECT

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

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

View file

@ -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();
};
}

View file

@ -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());
}

View file

@ -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());
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;i<topicsList->getItemCount();i++)
{
std::string keyWord = topicsList->getItemNameAt(i);
if (keyWord != "")
if (separatorReached && keyWord != "")
addColorInString(text,keyWord,"#686EBA","#B29154");
else
separatorReached = true;
}
return text;
}

View file

@ -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<std::string>& 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::string> (std::cout, ", "));
std::cout << std::endl;
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);

View file

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

View file

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

View file

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

View file

@ -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();
}

View file

@ -19,6 +19,10 @@ namespace MWMechanics
Spells mSpells;
ActiveSpells mActiveSpells;
MagicEffects mMagicEffects;
int mHello;
int mFight;
int mFlee;
int mAlarm;
};
}

View file

@ -7,6 +7,8 @@
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#include "../mwmechanics/creaturestats.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
@ -88,6 +90,95 @@ namespace MWScript
}
};
template<class R>
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<arg0; ++i) runtime.pop();
std::cout << "AiWanter" << std::endl;
}
};
template<class R>
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 R>
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 R>
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 R>
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<ExplicitRef>);
interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort<ImplicitRef>);
interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscort<ExplicitRef>);
interpreter.installSegment3 (opcodeAiWander, new OpAiWander<ImplicitRef>);
interpreter.installSegment3 (opcodeAiWanderExplicit, new OpAiWander<ExplicitRef>);
interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone<ImplicitRef>);
interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit,
new OpGetAiPackageDone<ExplicitRef>);
interpreter.installSegment5 (opcodeSetHello, new OpSetHello<ImplicitRef>);
interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello<ExplicitRef>);
interpreter.installSegment5 (opcodeSetFight, new OpSetFight<ImplicitRef>);
interpreter.installSegment5 (opcodeSetFightExplicit, new OpSetFight<ExplicitRef>);
interpreter.installSegment5 (opcodeSetFlee, new OpSetFlee<ImplicitRef>);
interpreter.installSegment5 (opcodeSetFleeExplicit, new OpSetFlee<ExplicitRef>);
interpreter.installSegment5 (opcodeSetAlarm, new OpSetAlarm<ImplicitRef>);
interpreter.installSegment5 (opcodeSetAlarmExplicit, new OpSetAlarm<ExplicitRef>);
}
}
}

View file

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

View file

@ -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?
};

View file

@ -11,7 +11,10 @@
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
#include <iostream>
@ -54,11 +57,71 @@ namespace MWScript
}
};
template<class R>
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 R>
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 R>
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 R>
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<ImplicitRef>);
interpreter.installSegment5 (opcodeForceRun, new OpForceRun<ImplicitRef>);
interpreter.installSegment5 (opcodeClearForceSneak, new OpClearForceSneak<ImplicitRef>);
interpreter.installSegment5 (opcodeForceSneak, new OpForceSneak<ImplicitRef>);
interpreter.installSegment5 (opcodeClearForceRunExplicit,
new OpClearForceRun<ExplicitRef>);
interpreter.installSegment5 (opcodeForceRunExplicit,
new OpForceRun<ExplicitRef>);
interpreter.installSegment5 (opcodeClearForceSneakExplicit,
new OpClearForceSneak<ExplicitRef>);
interpreter.installSegment5 (opcodeForceSneakExplicit,
new OpForceSneak<ExplicitRef>);
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -11,6 +11,7 @@
#include <components/compiler/scanner.hpp>
#include <components/compiler/context.hpp>
#include <components/compiler/exception.hpp>
#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<Interpreter::Type_Code> 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; i<size; ++i)
if (script->varNames.at (i+offset)==variable)
return i;
throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId);
}
}

View file

@ -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.
};
};

View file

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

View file

@ -7,7 +7,6 @@ namespace MWWorld
{
void ActionAlchemy::execute()
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy);
}
}

View file

@ -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();
}

View file

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

View file

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

View file

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

View file

@ -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();
}

View file

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

View file

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

View file

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

View file

@ -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<Interpreter::Type_Code> 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;
}

View file

@ -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<Interpreter::Type_Code>& mCode;
State mState;
std::string mName;
std::string mMemberName;
int mButtons;
std::string mExplicit;
char mType;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<RigidBody&>(*resultCallback1.m_collisionObject).mName;
name = static_cast<const RigidBody&>(*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<PairCachingGhostObject&>(*resultCallback2.m_collisionObject).mName;
name = static_cast<const PairCachingGhostObject&>(*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<float, btCollisionObject*> > results = resultCallback1.results;
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
MyRayResultCallback resultCallback2;
resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL;
dynamicsWorld->rayTest(from, to, resultCallback2);
std::vector< std::pair<float, btCollisionObject*> > actorResults = resultCallback2.results;
std::vector< std::pair<float, const btCollisionObject*> > actorResults = resultCallback2.results;
std::vector< std::pair<float, std::string> > results2;
for (std::vector< std::pair<float, btCollisionObject*> >::iterator it=results.begin();
for (std::vector< std::pair<float, const btCollisionObject*> >::iterator it=results.begin();
it != results.end(); ++it)
{
results2.push_back( std::make_pair( (*it).first, static_cast<RigidBody&>(*(*it).second).mName ) );
results2.push_back( std::make_pair( (*it).first, static_cast<const RigidBody&>(*(*it).second).mName ) );
}
for (std::vector< std::pair<float, btCollisionObject*> >::iterator it=actorResults.begin();
for (std::vector< std::pair<float, const btCollisionObject*> >::iterator it=actorResults.begin();
it != actorResults.end(); ++it)
{
results2.push_back( std::make_pair( (*it).first, static_cast<PairCachingGhostObject&>(*(*it).second).mName ) );
results2.push_back( std::make_pair( (*it).first, static_cast<const PairCachingGhostObject&>(*(*it).second).mName ) );
}
std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp);

View file

@ -278,7 +278,7 @@ namespace Physic
return false;
}
std::vector < std::pair<float, btCollisionObject*> > results;
std::vector < std::pair<float, const btCollisionObject*> > results;
};
}}

View file

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

View file

@ -190,7 +190,6 @@ struct playerMove
int waterHeight;
bool hasWater;
bool isInterior;
//Object* traceObj;
OEngine::Physic::PhysicEngine* mEngine;
};

View file

@ -110,6 +110,7 @@ Nikolay “corristo” Kasyanov
Pieter “pvdk” van der Kloet
Roman "Kromgart" Melnik
Sebastian “swick” Wick
Sylvain "Garvek" T.
Retired Developers:
Ardekantur