Merge branch 'AI' of git@github.com:gugus/openmw.git into AI

This commit is contained in:
gus 2013-03-31 09:25:14 +00:00
commit e150e22652
157 changed files with 2561 additions and 871 deletions

1
.gitignore vendored
View file

@ -17,3 +17,4 @@ data
CMakeLists.txt.user
*.swp
*.swo
*.kate-swp

View file

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version
set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 21)
set (OPENMW_VERSION_MINOR 22)
set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -257,10 +257,10 @@ set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1)
# Set up Ogre plugin folder & debug suffix
if (APPLE)
# Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt)
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="")
# Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt)
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="")
else ()
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
endif()
add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}")
@ -278,9 +278,9 @@ add_subdirectory(files/mygui)
# Specify build paths
if (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
else (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
endif (APPLE)
# Other files
@ -334,7 +334,7 @@ if(DPKG_PROGRAM)
#Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
#Install global configuration files
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
@ -355,7 +355,7 @@ if(DPKG_PROGRAM)
Data files from the original game is required to run it.")
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW bsatool;Bsatool esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter")
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW bsatool;Bsatool esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
@ -384,6 +384,7 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/Release/mwiniimport.exe"
"${OpenMW_BINARY_DIR}/Release/omwlauncher.exe"
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".")
@ -409,8 +410,8 @@ if(WIN32)
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico")
SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp")
SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe")
@ -510,10 +511,10 @@ if (WIN32)
4986 # Undocumented warning that occurs in the crtdbg.h file
4996 # Function was declared deprecated
# cause by ogre extensivly
4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
# cause by ogre extensivly
4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
# OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type
@ -525,7 +526,7 @@ if (WIN32)
4309 # Variable overflow, trying to store 128 in a signed char for example
4355 # Using 'this' in member initialization list
4701 # Potentially uninitialized local variable used
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
)
foreach(d ${WARNINGS_DISABLE})
@ -536,12 +537,12 @@ if (WIN32)
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
if (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
if (BUILD_BSATOOL)
if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_BSATOOL)
endif (BUILD_BSATOOL)
if (BUILD_ESMTOOL)
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_ESMTOOL)
@ -666,9 +667,9 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
IF(BUILD_LAUNCHER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
ENDIF(BUILD_LAUNCHER)
IF(BUILD_BSATOOL)
IF(BUILD_BSATOOL)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
ENDIF(BUILD_BSATOOL)
ENDIF(BUILD_BSATOOL)
IF(BUILD_ESMTOOL)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
ENDIF(BUILD_ESMTOOL)
@ -680,7 +681,7 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
ENDIF(BUILD_OPENCS)
# Install icon and .desktop
INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "${ICONDIR}")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications")
# Install global configuration files

View file

@ -227,7 +227,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
std::cout << " Refnum: " << ref.mRefnum << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n";
std::cout << " Owner: '" << ref.mOwner << "'\n";
std::cout << " INTV: " << ref.mIntv << " NAM9: " << ref.mIntv << std::endl;
std::cout << " Uses/health: " << ref.mCharge << " NAM9: " << ref.mNam9 << std::endl;
}
}

View file

@ -275,7 +275,7 @@ RecordBase::create(ESM::NAME type)
}
case ESM::REC_LOCK:
{
record = new EsmTool::Record<ESM::Tool>;
record = new EsmTool::Record<ESM::Lockpick>;
break;
}
case ESM::REC_LTEX:
@ -864,14 +864,13 @@ void Record<ESM::Light>::print()
}
template<>
void Record<ESM::Tool>::print()
void Record<ESM::Lockpick>::print()
{
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -886,8 +885,6 @@ void Record<ESM::Probe>::print()
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
// BUG? No Type Label?
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -902,7 +899,6 @@ void Record<ESM::Repair>::print()
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl;

View file

@ -104,7 +104,7 @@ namespace EsmTool
template<> void Record<ESM::CreatureLevList>::print();
template<> void Record<ESM::ItemLevList>::print();
template<> void Record<ESM::Light>::print();
template<> void Record<ESM::Tool>::print();
template<> void Record<ESM::Lockpick>::print();
template<> void Record<ESM::Probe>::print();
template<> void Record<ESM::Repair>::print();
template<> void Record<ESM::LandTexture>::print();

View file

@ -12,7 +12,7 @@ set(LAUNCHER
utils/checkablemessagebox.cpp
utils/textinputdialog.cpp
launcher.rc
${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc
)
set(LAUNCHER_HEADER
@ -43,10 +43,10 @@ set(LAUNCHER_HEADER_MOC
)
set(LAUNCHER_UI
../../files/ui/datafilespage.ui
../../files/ui/graphicspage.ui
../../files/ui/mainwindow.ui
../../files/ui/playpage.ui
${CMAKE_SOURCE_DIR}/files/ui/datafilespage.ui
${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui
${CMAKE_SOURCE_DIR}/files/ui/mainwindow.ui
${CMAKE_SOURCE_DIR}/files/ui/playpage.ui
)
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})

View file

@ -1,6 +1,9 @@
#include "datafilespage.hpp"
#include <QtGui>
#include <QPushButton>
#include <QMessageBox>
#include <QCheckBox>
#include <QMenu>
#include <components/files/configurationmanager.hpp>
@ -144,7 +147,7 @@ void DataFilesPage::setupDataFiles()
profilesComboBox->addItems(profiles);
// Add the current profile if empty
if (profilesComboBox->findText(profile) == -1)
if (profilesComboBox->findText(profile) == -1 && !profile.isEmpty())
profilesComboBox->addItem(profile);
if (profilesComboBox->findText(QString("Default")) == -1)

View file

@ -1,6 +1,8 @@
#include "graphicspage.hpp"
#include <QtGui>
#include <QDesktopWidget>
#include <QMessageBox>
#include <QDir>
#include <cstdlib>
@ -257,7 +259,7 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
for (opt_it = i->second.possibleValues.begin ();
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
{
QRegExp resolutionRe(QString("(\\d+) x (\\d+)"));
QRegExp resolutionRe(QString("(\\d+) x (\\d+).*"));
QString resolution = QString::fromStdString(*opt_it).simplified();
if (resolutionRe.exactMatch(resolution)) {
@ -266,16 +268,17 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
int height = resolutionRe.cap(2).toInt();
QString aspect = getAspect(width, height);
QString cleanRes = resolutionRe.cap(1) + QString(" x ") + resolutionRe.cap(2);
if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) {
resolution.append(tr("\t(Wide ") + aspect + ")");
cleanRes.append(tr("\t(Wide ") + aspect + ")");
} else if (aspect == QLatin1String("4:3")) {
resolution.append(tr("\t(Standard 4:3)"));
cleanRes.append(tr("\t(Standard 4:3)"));
}
// do not add duplicate resolutions
if (!result.contains(resolution))
result.append(resolution);
if (!result.contains(cleanRes))
result.append(cleanRes);
}
}
}

View file

@ -1 +0,0 @@
IDI_ICON1 ICON DISCARDABLE "resources/images/openmw.ico"

View file

@ -1,6 +1,15 @@
#include "maindialog.hpp"
#include <QtGui>
#include <QFontDatabase>
#include <QInputDialog>
#include <QFileDialog>
#include <QCloseEvent>
#include <QTextCodec>
#include <QProcess>
#include <QFile>
#include <QDir>
#include <QDebug>
#include "utils/checkablemessagebox.hpp"
@ -113,6 +122,51 @@ void MainDialog::createPages()
bool MainDialog::showFirstRunDialog()
{
QStringList iniPaths;
foreach (const QString &path, mGameSettings.getDataDirs()) {
QDir dir(path);
dir.setPath(dir.canonicalPath()); // Resolve symlinks
if (!dir.cdUp())
continue; // Cannot move from Data Files
if (dir.exists(QString("Morrowind.ini")))
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
}
// Ask the user where the Morrowind.ini is
if (iniPaths.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error detecting Morrowind configuration"));
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(QObject::tr("<br><b>Could not find Morrowind.ini</b><br><br> \
OpenMW needs to import settings from this file.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
QString iniFile;
if (msgBox.clickedButton() == dirSelectButton) {
iniFile = QFileDialog::getOpenFileName(
NULL,
QObject::tr("Select configuration file"),
QDir::currentPath(),
QString(tr("Morrowind configuration file (*.ini)")));
}
if (iniFile.isEmpty())
return false; // Cancel was clicked;
QFileInfo info(iniFile);
iniPaths.clear();
iniPaths.append(info.absoluteFilePath());
}
CheckableMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Morrowind installation detected"));
@ -120,7 +174,6 @@ bool MainDialog::showFirstRunDialog()
int size = QApplication::style()->pixelMetric(QStyle::PM_MessageBoxIconSize);
msgBox.setIconPixmap(icon.pixmap(size, size));
QAbstractButton *importerButton =
msgBox.addButton(tr("Import"), QDialogButtonBox::AcceptRole); // ActionRole doesn't work?!
QAbstractButton *skipButton =
@ -129,54 +182,28 @@ bool MainDialog::showFirstRunDialog()
Q_UNUSED(skipButton); // Surpress compiler unused warning
msgBox.setStandardButtons(QDialogButtonBox::NoButton);
msgBox.setText(tr("<br><b>An existing Morrowind installation was detected</b><br><br> \
Would you like to import settings from Morrowind.ini?<br>"));
msgBox.setText(tr("<br><b>An existing Morrowind configuration was detected</b><br> \
<br>Would you like to import settings from Morrowind.ini?<br> \
<br><b>Warning: In most cases OpenMW needs these settings to run properly</b><br>"));
msgBox.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)"));
msgBox.exec();
if (msgBox.clickedButton() == importerButton) {
QStringList iniPaths;
foreach (const QString &path, mGameSettings.getDataDirs()) {
QDir dir(path);
dir.setPath(dir.canonicalPath()); // Resolve symlinks
if (!dir.cdUp())
continue; // Cannot move from Data Files
if (dir.exists(QString("Morrowind.ini")))
iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini")));
}
if (iniPaths.isEmpty()) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error reading Morrowind configuration file"));
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(QObject::tr("<br><b>Could not find Morrowind.ini</b><br><br> \
The problem may be due to an incomplete installation of Morrowind.<br> \
Reinstalling Morrowind may resolve the problem."));
msgBox.exec();
return false;
}
if (iniPaths.count() > 1) {
// Multiple Morrowind.ini files found
bool ok;
QString path = QInputDialog::getItem(this, tr("Multiple configurations found"),
QString path = QInputDialog::getItem(this, tr("Multiple configurations found"),
tr("<br><b>There are multiple Morrowind.ini files found.</b><br><br> \
Please select the one you wish to import from:"), iniPaths, 0, false, &ok);
if (ok && !path.isEmpty()) {
iniPaths.clear();
iniPaths.append(path);
} else {
// Cancel was clicked TODO: should we abort here?
return false;
}
if (ok && !path.isEmpty()) {
iniPaths.clear();
iniPaths.append(path);
} else {
// Cancel was clicked
return false;
}
}
// Create the file if it doesn't already exist, else the importer will fail
@ -204,9 +231,13 @@ bool MainDialog::showFirstRunDialog()
QStringList arguments;
if (msgBox.isChecked())
arguments.append(QString("-g"));
arguments.append(QString("--game-files"));
arguments.append(QString("--encoding"));
arguments.append(mGameSettings.value(QString("encoding"), QString("win1252")));
arguments.append(QString("--ini"));
arguments.append(iniPaths.first());
arguments.append(QString("--cfg"));
arguments.append(path);
if (!startProgram(QString("mwiniimport"), arguments, false))
@ -218,7 +249,7 @@ bool MainDialog::showFirstRunDialog()
// Add a new profile
if (msgBox.isChecked()) {
mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported"));
mLauncherSettings.setValue(QString("Profiles/currentprofile"), QString("Imported"));
mLauncherSettings.remove(QString("Profiles/Imported/master"));
mLauncherSettings.remove(QString("Profiles/Imported/plugin"));
@ -659,7 +690,7 @@ bool MainDialog::startProgram(const QString &name, const QStringList &arguments,
return false;
}
if (process.exitCode() != 0) {
if (process.exitCode() != 0 || process.exitStatus() == QProcess::CrashExit) {
QString error(process.readAllStandardError());
error.append(tr("\nArguments:\n"));
error.append(arguments.join(" "));

View file

@ -1,6 +1,10 @@
#include "playpage.hpp"
#include <QtGui>
#include <QListView>
#ifdef Q_OS_MAC
#include <QPlastiqueStyle>
#endif
PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
{

View file

@ -22,3 +22,8 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(mwiniimport gcov)
endif()
if(DPKG_PROGRAM)
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
endif()

View file

@ -35,7 +35,7 @@ opencs_units (model/tools
)
opencs_units_noqt (model/tools
stage verifier mandatoryid
stage verifier mandatoryid skillcheck
)

View file

@ -2,7 +2,7 @@
#include "document.hpp"
#include <cassert>
#include <QDebug>
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
{
@ -150,6 +150,10 @@ void CSMDoc::Document::addOptionalGlobals()
ESM::Global global;
global.mId = sGlobals[i];
global.mValue.setType (ESM::VT_Long);
if (i==0)
global.mValue.setInteger (1); // dayspassed starts counting at 1
addOptionalGlobal (global);
}
}
@ -189,15 +193,25 @@ void CSMDoc::Document::createBase()
record.mId = sGlobals[i];
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int);
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Long);
if (i==0)
if (i==0 || i==1)
record.mValue.setInteger (1);
getData().getGlobals().add (record);
}
/// \todo add GMSTs
for (int i=0; i<27; ++i)
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::Skill::getIndexToId (record.mIndex);
record.blank();
getData().getSkills().add (record);
}
}
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
@ -214,7 +228,7 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
if (new_ && files.size()==1)
createBase();
else if (files.size()>1)
else
{
std::vector<boost::filesystem::path>::const_iterator end = files.end();

View file

@ -0,0 +1,37 @@
#include "skillcheck.hpp"
#include <sstream>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
: mSkills (skills)
{}
int CSMTools::SkillCheckStage::setup()
{
return mSkills.getSize();
}
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);
for (int i=0; i<4; ++i)
if (skill.mData.mUseValue[i]<0)
{
std::ostringstream stream;
stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative";
messages.push_back (stream.str());
}
if (skill.mDescription.empty())
messages.push_back (id.toString() + "|" + skill.mId + " has an empty description");
}

View file

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SKILLCHECK_H
#define CSM_TOOLS_SKILLCHECK_H
#include <components/esm/loadskil.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that skill records are internally consistent
class SkillCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
public:
SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View file

@ -12,6 +12,7 @@
#include "reportmodel.hpp"
#include "mandatoryid.hpp"
#include "skillcheck.hpp"
CSMTools::Operation *CSMTools::Tools::get (int type)
{
@ -51,6 +52,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills()));
}
return mVerifier;

View file

@ -31,7 +31,9 @@ namespace CSMWorld
Display_Float,
Display_Var,
Display_GmstVarType,
Display_GlobalVarType
Display_GlobalVarType,
Display_Specialisation,
Display_Attribute
};
std::string mTitle;

View file

@ -1,6 +1,8 @@
#ifndef CSM_WOLRD_COLUMNS_H
#define CSM_WOLRD_COLUMNS_H
#include <boost/lexical_cast.hpp>
#include "columnbase.hpp"
namespace CSMWorld
@ -35,7 +37,7 @@ namespace CSMWorld
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mId.c_str();
return QString::fromUtf8 (record.get().mId.c_str());
}
virtual bool isEditable() const
@ -127,17 +129,17 @@ namespace CSMWorld
{
case ESM::VT_String:
return record.get().mValue.getString().c_str(); break;
return QString::fromUtf8 (record.get().mValue.getString().c_str());
case ESM::VT_Int:
case ESM::VT_Short:
case ESM::VT_Long:
return record.get().mValue.getInteger(); break;
return record.get().mValue.getInteger();
case ESM::VT_Float:
return record.get().mValue.getFloat(); break;
return record.get().mValue.getFloat();
default: return QVariant();
}
@ -177,6 +179,112 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct DescriptionColumn : public Column<ESXRecordT>
{
DescriptionColumn() : Column<ESXRecordT> ("Description", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mDescription.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mDescription = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SpecialisationColumn : public Column<ESXRecordT>
{
SpecialisationColumn() : Column<ESXRecordT> ("Specialisation", ColumnBase::Display_Specialisation) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mSpecialization;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mSpecialization = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct UseValueColumn : public Column<ESXRecordT>
{
int mIndex;
UseValueColumn (int index)
: Column<ESXRecordT> ("Use value #" + boost::lexical_cast<std::string> (index),
ColumnBase::Display_Float), mIndex (index)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mUseValue[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mUseValue[mIndex] = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AttributeColumn : public Column<ESXRecordT>
{
AttributeColumn() : Column<ESXRecordT> ("Attribute", ColumnBase::Display_Attribute) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAttribute;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAttribute = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

View file

@ -1,7 +1,7 @@
#include "commands.hpp"
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include "idtableproxymodel.hpp"
#include "idtable.hpp"

View file

@ -3,7 +3,7 @@
#include <stdexcept>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp>
@ -12,7 +12,7 @@
#include "idtable.hpp"
#include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractTableModel *model, UniversalId::Type type1,
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2)
{
mModels.push_back (model);
@ -36,13 +36,22 @@ CSMWorld::Data::Data()
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
mSkills.addColumn (new StringIdColumn<ESM::Skill>);
mSkills.addColumn (new RecordStateColumn<ESM::Skill>);
mSkills.addColumn (new AttributeColumn<ESM::Skill>);
mSkills.addColumn (new SpecialisationColumn<ESM::Skill>);
for (int i=0; i<4; ++i)
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
}
CSMWorld::Data::~Data()
{
for (std::vector<QAbstractTableModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
delete *iter;
}
@ -66,9 +75,19 @@ CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
return mGmsts;
}
QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id)
const CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills() const
{
std::map<UniversalId::Type, QAbstractTableModel *>::iterator iter = mModelIndex.find (id.getType());
return mSkills;
}
CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills()
{
return mSkills;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
if (iter==mModelIndex.end())
throw std::logic_error ("No table model available for " + id.toString());
@ -102,7 +121,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
{
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
case ESM::REC_GMST: mGmsts.load (reader, base); break;
case ESM::REC_SKIL: mSkills.load (reader, base); break;
default:

View file

@ -8,11 +8,12 @@
#include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp>
#include "idcollection.hpp"
#include "universalid.hpp"
class QAbstractTableModel;
class QAbstractItemModel;
namespace CSMWorld
{
@ -20,14 +21,15 @@ namespace CSMWorld
{
IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts;
std::vector<QAbstractTableModel *> mModels;
std::map<UniversalId::Type, QAbstractTableModel *> mModelIndex;
IdCollection<ESM::Skill> mSkills;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
// not implemented
Data (const Data&);
Data& operator= (const Data&);
void addModel (QAbstractTableModel *model, UniversalId::Type type1,
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None);
public:
@ -44,7 +46,11 @@ namespace CSMWorld
IdCollection<ESM::GameSetting>& getGmsts();
QAbstractTableModel *getTableModel (const UniversalId& id);
const IdCollection<ESM::Skill>& getSkills() const;
IdCollection<ESM::Skill>& getSkills();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///
/// \note The returned table may either be the model for the ID itself or the model that

View file

@ -74,6 +74,8 @@ namespace CSMWorld
virtual const RecordBase& getRecord (const std::string& id) const = 0;
virtual const RecordBase& getRecord (int index) const = 0;
virtual void load (ESM::ESMReader& reader, bool base) = 0;
};
@ -139,7 +141,9 @@ namespace CSMWorld
///
/// \attention Throw san exception, if the type of \a record does not match.
virtual const RecordBase& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base);
@ -373,11 +377,18 @@ namespace CSMWorld
}
template<typename ESXRecordT>
const RecordBase& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
{
int index = getIndex (id);
return mRecords.at (index);
}
template<typename ESXRecordT>
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (int index) const
{
return mRecords.at (index);
}
}
#endif

View file

@ -96,6 +96,25 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren
return true;
}
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
{
if (parent.isValid())
return QModelIndex();
if (row<0 || row>=mIdCollection->getSize())
return QModelIndex();
if (column<0 || column>=mIdCollection->getColumns())
return QModelIndex();
return createIndex (row, column);
}
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
{
return QModelIndex();
}
void CSMWorld::IdTable::addRecord (const std::string& id)
{
int index = mIdCollection->getSize();

View file

@ -1,14 +1,14 @@
#ifndef CSM_WOLRD_IDTABLE_H
#define CSM_WOLRD_IDTABLE_H
#include <QAbstractTableModel>
#include <QAbstractItemModel>
namespace CSMWorld
{
class IdCollectionBase;
class RecordBase;
class IdTable : public QAbstractTableModel
class IdTable : public QAbstractItemModel
{
Q_OBJECT
@ -39,6 +39,11 @@ namespace CSMWorld
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex())
const;
virtual QModelIndex parent (const QModelIndex& index) const;
void addRecord (const std::string& id);
QModelIndex getModelIndex (const std::string& id, int column) const;

View file

@ -62,7 +62,7 @@ namespace CSMWorld
if (mState==State_Erased)
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly ? mBase : mModified;
return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
}
template <typename ESXRecordT>
@ -81,9 +81,7 @@ namespace CSMWorld
throw std::logic_error ("attempt to modify a deleted record");
mModified = modified;
if (mState!=State_ModifiedOnly)
mState = mBase==mModified ? State_BaseOnly : State_Modified;
mState = State_Modified;
}
template <typename ESXRecordT>

View file

@ -19,6 +19,7 @@ namespace
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -27,6 +28,7 @@ namespace
{
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -43,7 +45,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId)
{
std::string::size_type index = universalId.find (':');
if (index==std::string::npos)
if (index!=std::string::npos)
{
std::string type = universalId.substr (0, index);

View file

@ -37,8 +37,9 @@ namespace CSMWorld
Type_Global,
Type_VerificationResults,
Type_Gmsts,
Type_Gmst
Type_Gmst,
Type_Skills,
Type_Skill
};
private:

View file

@ -86,6 +86,10 @@ void CSVDoc::View::setupWorldMenu()
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
world->addAction (gmsts);
QAction *skills = new QAction (tr ("Skills"), this);
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
world->addAction (skills);
mVerify = new QAction (tr ("&Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
world->addAction (mVerify);
@ -244,6 +248,11 @@ void CSVDoc::View::addGmstsSubView()
addSubView (CSMWorld::UniversalId::Type_Gmsts);
}
void CSVDoc::View::addSkillsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Skills);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

View file

@ -116,6 +116,7 @@ namespace CSVDoc
void addGmstsSubView();
void addSkillsSubView();
};
}

View file

@ -38,6 +38,17 @@ void CSVDoc::ViewManager::updateIndices()
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{
static const char *sSpecialisations[] =
{
"Combat", "Magic", "Stealth", 0
};
static const char *sAttributes[] =
{
"Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
"Luck", 0
};
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
@ -45,6 +56,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
new CSVWorld::EnumDelegateFactory (sSpecialisations));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
new CSVWorld::EnumDelegateFactory (sAttributes));
}
CSVDoc::ViewManager::~ViewManager()

View file

@ -3,7 +3,7 @@
#include <QGridLayout>
#include <QLabel>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QLineEdit>
@ -24,7 +24,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
widget->setLayout (layout);
QAbstractTableModel *model = document.getData().getTableModel (id);
QAbstractItemModel *model = document.getData().getTableModel (id);
int columns = model->columnCount();

View file

@ -1,6 +1,7 @@
#include "enumdelegate.hpp"
#include <cassert>
#include <stdexcept>
#include <QComboBox>
@ -89,6 +90,16 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte
}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names)
{
assert (names);
for (int i=0; names[i]; ++i)
add (i, names[i]);
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{

View file

@ -45,6 +45,11 @@ namespace CSVWorld
public:
EnumDelegateFactory();
EnumDelegateFactory (const char **names);
///< \param names Array of char pointer with a 0-pointer as end mark
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.

View file

@ -14,6 +14,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Gmsts,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Skills,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Global,
new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
}

View file

@ -31,6 +31,7 @@ add_openmw_dir (mwgui
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons
merchantrepair repair
)
add_openmw_dir (mwdialogue
@ -53,7 +54,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp
esmstore store recordcmp fallback actionrepair
)
add_openmw_dir (mwclass
@ -64,7 +65,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate
aiescort aiactivate repair
)
add_openmw_dir (mwbase

View file

@ -41,6 +41,8 @@ namespace MWBase
virtual void goodbyeSelected() = 0;
virtual void questionAnswered (const std::string& answer) = 0;
virtual bool checkServiceRefused () = 0;
virtual void persuade (int type) = 0;
virtual int getTemporaryDispositionChange () const = 0;
virtual void applyTemporaryDispositionChange (int delta) = 0;

View file

@ -91,6 +91,8 @@ namespace MWBase
virtual bool isGuiMode() const = 0;
virtual bool isConsoleMode() const = 0;
virtual void toggleVisible (MWGui::GuiWindow wnd) = 0;
/// Disallow all inventory mode windows
@ -236,6 +238,8 @@ namespace MWBase
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
virtual void startTraining(MWWorld::Ptr actor) = 0;
virtual void startRepair(MWWorld::Ptr actor) = 0;
virtual void startRepairItem(MWWorld::Ptr item) = 0;
virtual void changePointer (const std::string& name) = 0;

View file

@ -46,6 +46,7 @@ namespace MWRender
namespace MWWorld
{
class Fallback;
class CellStore;
class Player;
class LocalScripts;
@ -103,11 +104,7 @@ namespace MWBase
virtual void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches) = 0;
virtual void setFallbackValues (const std::map<std::string, std::string>& fallbackMap) = 0;
virtual std::string getFallback (const std::string& key) const = 0;
virtual std::string getFallback (const std::string& key, const std::string& def) const = 0;
virtual const MWWorld::Fallback *getFallback () const = 0;
virtual MWWorld::Player& getPlayer() = 0;

View file

@ -247,8 +247,9 @@ namespace MWClass
text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor);
/// \todo store the current armor health somewhere
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth;
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/"
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")";
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");

View file

@ -191,6 +191,12 @@ namespace MWClass
return info;
}
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
{
/// \todo add Shield magic effect magnitude here, controlled by a GMST (Vanilla vs MCP behaviour)
return 0.f;
}
float Creature::getCapacity (const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
@ -203,9 +209,9 @@ namespace MWClass
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (8)).mMagnitude; // feather
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).mMagnitude;
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (7)).mMagnitude; // burden
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).mMagnitude;
if (weight<0)
weight = 0;

View file

@ -54,6 +54,9 @@ 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 float getArmorRating (const MWWorld::Ptr& ptr) const;
///< @return combined armor rating of this actor
virtual bool isEssential (const MWWorld::Ptr& ptr) const;
///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)

View file

@ -1,7 +1,7 @@
#include "lockpick.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadlock.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -41,8 +41,8 @@ namespace MWClass
std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
assert(ref->mBase != NULL);
const std::string &model = ref->mBase->mModel;
@ -54,8 +54,8 @@ namespace MWClass
std::string Lockpick::getName (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mName;
}
@ -75,8 +75,8 @@ namespace MWClass
std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mScript;
}
@ -92,8 +92,8 @@ namespace MWClass
int Lockpick::getValue (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mData.mValue;
}
@ -102,7 +102,7 @@ namespace MWClass
{
boost::shared_ptr<Class> instance (new Lockpick);
registerClass (typeid (ESM::Tool).name(), instance);
registerClass (typeid (ESM::Lockpick).name(), instance);
}
std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr) const
@ -117,24 +117,24 @@ namespace MWClass
std::string Lockpick::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return ref->mBase->mIcon;
}
bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return (ref->mBase->mName != "");
}
MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
MWGui::ToolTipInfo info;
info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
@ -142,9 +142,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -171,8 +171,8 @@ namespace MWClass
MWWorld::Ptr
Lockpick::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{
MWWorld::LiveCellRef<ESM::Tool> *ref =
ptr.get<ESM::Tool>();
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell);
}

View file

@ -471,9 +471,9 @@ namespace MWClass
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (8)).mMagnitude; // feather
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).mMagnitude;
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (7)).mMagnitude; // burden
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).mMagnitude;
if (weight<0)
weight = 0;
@ -505,12 +505,75 @@ namespace MWClass
stats.useSkill (skill, *class_, usageType);
}
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int ratings[MWWorld::InventoryStore::Slots];
int iBaseArmorSkill = gmst.find("iBaseArmorSkill")->getInt();
float fUnarmoredBase1 = gmst.find("fUnarmoredBase1")->getFloat();
float fUnarmoredBase2 = gmst.find("fUnarmoredBase2")->getFloat();
int unarmoredSkill = MWWorld::Class::get(ptr).getNpcStats(ptr).getSkill(ESM::Skill::Unarmored).getModified();
for (int i = 0; i < MWWorld::InventoryStore::Slots; ++i)
{
MWWorld::ContainerStoreIterator it = invStore.getSlot(i);
if (it == invStore.end() || it->getTypeName() != typeid(ESM::Armor).name())
{
// unarmored
ratings[i] = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill);
}
else
{
MWWorld::LiveCellRef<ESM::Armor> *ref =
it->get<ESM::Armor>();
int armorSkillType = MWWorld::Class::get(*it).getEquipmentSkill(*it);
int armorSkill = MWWorld::Class::get(ptr).getNpcStats(ptr).getSkill(armorSkillType).getModified();
if (ref->mBase->mData.mWeight == 0)
ratings[i] = ref->mBase->mData.mArmor;
else
ratings[i] = ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill;
}
}
float shield = MWWorld::Class::get(ptr).getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude;
return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3
+ (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet]
+ ratings[MWWorld::InventoryStore::Slot_Greaves] + ratings[MWWorld::InventoryStore::Slot_Boots]
+ ratings[MWWorld::InventoryStore::Slot_LeftPauldron] + ratings[MWWorld::InventoryStore::Slot_RightPauldron]
) * 0.1
+ (ratings[MWWorld::InventoryStore::Slot_LeftGauntlet] + MWWorld::InventoryStore::Slot_RightGauntlet)
* 0.05
+ shield;
}
void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
{
y = 0;
x = 0;
}
void Npc::adjustScale(const MWWorld::Ptr &ptr, float &scale) const
{
MWWorld::LiveCellRef<ESM::NPC> *ref =
ptr.get<ESM::NPC>();
const ESM::Race* race =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(ref->mBase->mRace);
if (ref->mBase->isMale())
scale *= race->mData.mHeight.mMale;
else
scale *= race->mData.mHeight.mFemale;
}
MWWorld::Ptr
Npc::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{

View file

@ -81,7 +81,7 @@ namespace MWClass
virtual bool getStance (const MWWorld::Ptr& ptr, Stance stance, bool ignoreForce = false)
const;
////< Check if a stance is active or not.
///< Check if a stance is active or not.
virtual float getSpeed (const MWWorld::Ptr& ptr) const;
///< Return movement speed.
@ -104,12 +104,17 @@ 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 float getArmorRating (const MWWorld::Ptr& ptr) const;
///< @return combined armor rating of this actor
virtual bool apply (const MWWorld::Ptr& ptr, const std::string& id,
const MWWorld::Ptr& actor) const;
///< Apply \a id on \a ptr.
/// \param actor Actor that is resposible for the ID being applied to \a ptr.
/// \return Any effect?
virtual void adjustScale (const MWWorld::Ptr &ptr, float &scale) const;
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const;
///< Inform actor \a ptr that a skill use has succeeded.

View file

@ -1,7 +1,7 @@
#include "probe.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadprob.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -141,9 +141,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");

View file

@ -1,7 +1,7 @@
#include "repair.hpp"
#include <components/esm/loadlocks.hpp>
#include <components/esm/loadrepa.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -12,6 +12,7 @@
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/actionrepair.hpp"
#include "../mwgui/tooltips.hpp"
@ -120,6 +121,19 @@ namespace MWClass
return (ref->mBase->mName != "");
}
bool Repair::hasItemHealth (const MWWorld::Ptr& ptr) const
{
return true;
}
int Repair::getItemMaxHealth (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
ptr.get<ESM::Repair>();
return ref->mBase->mData.mUses;
}
MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
@ -131,9 +145,9 @@ namespace MWClass
std::string text;
/// \todo store remaining uses somewhere
int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses;
text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses);
text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses);
text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality);
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
@ -156,4 +170,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mRepairs.insert(*ref), &cell);
}
boost::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr) const
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionRepair(ptr));
}
}

View file

@ -49,6 +49,18 @@ namespace MWClass
///< Return name of inventory icon.
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu (default implementation: return a
/// null action).
virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const;
///< \return Item health data available? (default implementation: false)
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
/// (default implementation: throw an exceoption)
};
}

View file

@ -75,7 +75,10 @@ namespace MWClass
bool Weapon::hasItemHealth (const MWWorld::Ptr& ptr) const
{
return true;
MWWorld::LiveCellRef<ESM::Weapon> *ref =
ptr.get<ESM::Weapon>();
return (ref->mBase->mData.mType < 11); // thrown weapons and arrows/bolts don't have health, only quantity
}
int Weapon::getItemMaxHealth (const MWWorld::Ptr& ptr) const
@ -334,9 +337,12 @@ namespace MWClass
}
}
/// \todo store the current weapon health somewhere
if (ref->mBase->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
{
int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth;
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/"
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
}
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");

View file

@ -241,7 +241,7 @@ namespace MWDialogue
}
}
void DialogueManager::executeTopic (const std::string& topic)
void DialogueManager::executeTopic (const std::string& topic, bool randomResponse)
{
Filter filter (mActor, mChoice, mTalkedTo);
@ -256,7 +256,7 @@ namespace MWDialogue
if (!infos.empty())
{
const ESM::DialInfo* info = infos[std::rand() % infos.size()];
const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0];
parseText (info->mResponse);
@ -367,6 +367,9 @@ namespace MWDialogue
if (services & ESM::NPC::Enchanting)
windowServices |= MWGui::DialogueWindow::Service_Enchant;
if (services & ESM::NPC::Repair)
windowServices |= MWGui::DialogueWindow::Service_Repair;
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->setServices (windowServices);
@ -505,7 +508,7 @@ namespace MWDialogue
text = "Bribe";
}
executeTopic (text + (success ? " Success" : " Fail"));
executeTopic (text + (success ? " Success" : " Fail"), true);
}
int DialogueManager::getTemporaryDispositionChange() const
@ -518,6 +521,37 @@ namespace MWDialogue
mTemporaryDispositionChange += delta;
}
bool DialogueManager::checkServiceRefused()
{
Filter filter (mActor, mChoice, mTalkedTo);
const MWWorld::Store<ESM::Dialogue> &dialogues =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
const ESM::Dialogue& dialogue = *dialogues.find ("Service Refusal");
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, false, false, true);
if (!infos.empty())
{
const ESM::DialInfo* info = infos[0];
parseText (info->mResponse);
const MWWorld::Store<ESM::GameSetting>& gmsts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
win->addTitle (gmsts.find ("sServiceRefusal")->getString());
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
executeScript (info->mResultScript);
return true;
}
return false;
}
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
{
std::vector<HyperTextToken> result;

View file

@ -48,7 +48,7 @@ namespace MWDialogue
void printError (const std::string& error);
void executeTopic (const std::string& topic);
void executeTopic (const std::string& topic, bool randomResponse=false);
public:
@ -65,6 +65,8 @@ namespace MWDialogue
virtual MWWorld::Ptr getActor() const;
///< Return the actor the player is currently talking to.
virtual bool checkServiceRefused ();
//calbacks for the GUI
virtual void keywordSelected (const std::string& keyword);
virtual void goodbyeSelected();

View file

@ -121,7 +121,7 @@ bool MWDialogue::Filter::testSelectStructs (const ESM::DialInfo& info) const
return true;
}
bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info) const
bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert) const
{
bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name());
@ -129,14 +129,19 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info) const
return true;
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
return actorDisposition >= info.mData.mDisposition;
// For service refusal, the disposition check is inverted. However, a value of 0 still means "always succeed".
return invert ? (info.mData.mDisposition == 0 || actorDisposition < info.mData.mDisposition)
: (actorDisposition >= info.mData.mDisposition);
}
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
{
if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name())
return select.isInverted();
if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name()))
// If the actor is a creature, we do not test the conditions applicable
// only to NPCs. Such conditions can never be satisfied, apart
// inverted ones (NotClass, NotRace, NotFaction return true
// because creatures are not of any race, class or faction).
return select.getType() == SelectWrapper::Type_Inverted;
switch (select.getType())
{
@ -144,6 +149,9 @@ bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select));
case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select);
case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select));
// We must not do the comparison for inverted functions (eg. Function_NotClass)
case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select);
}
return true;
@ -412,25 +420,49 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
return false;
case SelectWrapper::Function_Id:
case SelectWrapper::Function_NotId:
return select.getName()==Misc::StringUtils::lowerCase (MWWorld::Class::get (mActor).getId (mActor));
return select.getName()!=Misc::StringUtils::lowerCase (MWWorld::Class::get (mActor).getId (mActor));
case SelectWrapper::Function_Faction:
case SelectWrapper::Function_NotFaction:
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mFaction)==select.getName();
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mFaction)!=select.getName();
case SelectWrapper::Function_Class:
case SelectWrapper::Function_NotClass:
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mClass)==select.getName();
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mClass)!=select.getName();
case SelectWrapper::Function_Race:
case SelectWrapper::Function_NotRace:
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mRace)==select.getName();
return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mRace)!=select.getName();
case SelectWrapper::Function_Cell:
case SelectWrapper::Function_NotCell:
return Misc::StringUtils::lowerCase (mActor.getCell()->mCell->mName)==select.getName();
return Misc::StringUtils::lowerCase (mActor.getCell()->mCell->mName)!=select.getName();
case SelectWrapper::Function_NotLocal:
{
std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor);
if (scriptName.empty())
// This actor has no attached script, so there is no local variable
return true;
const ESM::Script *script =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName);
std::string name = select.getName();
int i = 0;
for (; i < static_cast<int> (script->mVarNames.size()); ++i)
if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name)
break;
if (i >= static_cast<int> (script->mVarNames.size()))
return true; // script does not have a variable of this name
return false;
}
case SelectWrapper::Function_SameGender:
@ -458,7 +490,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_PcCorprus:
return MWWorld::Class::get (player).getCreatureStats (player).
getMagicEffects().get (132).mMagnitude!=0;
getMagicEffects().get (ESM::MagicEffect::Corprus).mMagnitude!=0;
case SelectWrapper::Function_PcExpelled:
{
@ -570,7 +602,7 @@ const ESM::DialInfo* MWDialogue::Filter::search (const ESM::Dialogue& dialogue,
}
std::vector<const ESM::DialInfo *> MWDialogue::Filter::list (const ESM::Dialogue& dialogue,
bool fallbackToInfoRefusal, bool searchAll) const
bool fallbackToInfoRefusal, bool searchAll, bool invertDisposition) const
{
std::vector<const ESM::DialInfo *> infos;
@ -582,7 +614,7 @@ std::vector<const ESM::DialInfo *> MWDialogue::Filter::list (const ESM::Dialogue
{
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter))
{
if (testDisposition (*iter)) {
if (testDisposition (*iter, invertDisposition)) {
infos.push_back(&*iter);
if (!searchAll)
break;
@ -604,7 +636,7 @@ std::vector<const ESM::DialInfo *> MWDialogue::Filter::list (const ESM::Dialogue
for (std::vector<ESM::DialInfo>::const_iterator iter = infoRefusalDialogue.mInfo.begin();
iter!=infoRefusalDialogue.mInfo.end(); ++iter)
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter)) {
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter, invertDisposition)) {
infos.push_back(&*iter);
if (!searchAll)
break;

View file

@ -30,8 +30,8 @@ namespace MWDialogue
bool testSelectStructs (const ESM::DialInfo& info) const;
///< Are all select structs matching?
bool testDisposition (const ESM::DialInfo& info) const;
///< Is the actor disposition toward the player high enough?
bool testDisposition (const ESM::DialInfo& info, bool invert=false) const;
///< Is the actor disposition toward the player high enough (or low enough, if \a invert is true)?
bool testSelectStruct (const SelectWrapper& select) const;
@ -54,7 +54,7 @@ namespace MWDialogue
Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer);
std::vector<const ESM::DialInfo *> list (const ESM::Dialogue& dialogue,
bool fallbackToInfoRefusal, bool searchAll) const;
bool fallbackToInfoRefusal, bool searchAll, bool invertDisposition=false) const;
const ESM::DialInfo* search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const;
///< Get a matching response for the requested dialogue.

View file

@ -112,12 +112,12 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() con
case '4': return Function_Journal;
case '5': return Function_Item;
case '6': return Function_Dead;
case '7': return Function_Id;
case '8': return Function_Faction;
case '9': return Function_Class;
case 'A': return Function_Race;
case 'B': return Function_Cell;
case 'C': return Function_Local;
case '7': return Function_NotId;
case '8': return Function_NotFaction;
case '9': return Function_NotClass;
case 'A': return Function_NotRace;
case 'B': return Function_NotCell;
case 'C': return Function_NotLocal;
}
return Function_None;
@ -219,7 +219,6 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
static const Function booleanFunctions[] =
{
Function_False,
Function_Id, Function_Faction, Function_Class, Function_Race, Function_Cell,
Function_SameGender, Function_SameRace, Function_SameFaction,
Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus,
Function_PcExpelled,
@ -231,6 +230,13 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
Function_None // end marker
};
static const Function invertedBooleanFunctions[] =
{
Function_NotId, Function_NotFaction, Function_NotClass,
Function_NotRace, Function_NotCell, Function_NotLocal,
Function_None // end marker
};
Function function = getFunction();
for (int i=0; integerFunctions[i]!=Function_None; ++i)
@ -245,21 +251,18 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
if (booleanFunctions[i]==function)
return Type_Boolean;
for (int i=0; invertedBooleanFunctions[i]!=Function_None; ++i)
if (invertedBooleanFunctions[i]==function)
return Type_Inverted;
return Type_None;
}
bool MWDialogue::SelectWrapper::isInverted() const
{
char type = mSelect.mSelectRule[1];
return type=='7' || type=='8' || type=='9' || type=='A' || type=='B' || type=='C';
}
bool MWDialogue::SelectWrapper::isNpcOnly() const
{
static const Function functions[] =
{
Function_Faction, SelectWrapper::Function_Class, SelectWrapper::Function_Race,
Function_NotFaction, Function_NotClass, Function_NotRace,
Function_SameGender, Function_SameRace, Function_SameFaction,
Function_PcSkill,
Function_PcExpelled,
@ -283,17 +286,17 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const
bool MWDialogue::SelectWrapper::selectCompare (int value) const
{
return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR
return selectCompareImp (mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare (float value) const
{
return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR
return selectCompareImp (mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare (bool value) const
{
return selectCompareImp (mSelect, static_cast<int> (value))!=isInverted(); // logic XOR
return selectCompareImp (mSelect, static_cast<int> (value));
}
std::string MWDialogue::SelectWrapper::getName() const

View file

@ -17,11 +17,12 @@ namespace MWDialogue
Function_Journal,
Function_Item,
Function_Dead,
Function_Id,
Function_Faction,
Function_Class,
Function_Race,
Function_Cell,
Function_NotId,
Function_NotFaction,
Function_NotClass,
Function_NotRace,
Function_NotCell,
Function_NotLocal,
Function_Local,
Function_Global,
Function_SameGender, Function_SameRace, Function_SameFaction,
@ -50,7 +51,8 @@ namespace MWDialogue
Type_None,
Type_Integer,
Type_Numeric,
Type_Boolean
Type_Boolean,
Type_Inverted
};
private:
@ -67,8 +69,6 @@ namespace MWDialogue
Type getType() const;
bool isInverted() const;
bool isNpcOnly() const;
///< \attention Do not call any of the select functions for this select struct!

View file

@ -12,6 +12,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/fallback.hpp"
namespace
{
@ -23,14 +24,13 @@ namespace
};
const ESM::Class::Specialization mSpecializations[3]={ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}; // The specialization for each answer
Step sGenerateClassSteps(int number) {
MWBase::World *world = MWBase::Environment::get().getWorld();
number++;
Step step = {world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_Question"),
{world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerOne"),
world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerTwo"),
world->getFallback("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerThree")},
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
Step step = {fallback->getFallbackString("Question_"+boost::lexical_cast<std::string>(number)+"_Question"),
{fallback->getFallbackString("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerOne"),
fallback->getFallbackString("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerTwo"),
fallback->getFallbackString("Question_"+boost::lexical_cast<std::string>(number)+"_AnswerThree")},
"vo\\misc\\chargen qa"+boost::lexical_cast<std::string>(number)+".wav"
};
return step;
@ -674,9 +674,6 @@ void CharacterCreation::showClassQuestionDialog()
void CharacterCreation::onGenerateClassBack()
{
if(mCreationStage < CSE_ClassChosen)
mCreationStage = CSE_ClassChosen;
mWM->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = 0;

View file

@ -45,7 +45,7 @@ namespace
mapping.push_back( typeid(ESM::Book).name() );
mapping.push_back( typeid(ESM::Light).name() );
mapping.push_back( typeid(ESM::Miscellaneous).name() );
mapping.push_back( typeid(ESM::Tool).name() );
mapping.push_back( typeid(ESM::Lockpick).name() );
mapping.push_back( typeid(ESM::Repair).name() );
mapping.push_back( typeid(ESM::Probe).name() );
@ -683,12 +683,18 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
// transfer everything into the player's inventory
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
std::vector<MWWorld::Ptr> equippedItems = getEquippedItems();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
int i=0;
for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter)
{
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) != equippedItems.end()
&& !mDisplayEquippedItems)
continue;
playerStore.add(*iter);
if (i==0)
@ -698,11 +704,11 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
iter->getRefData().setCount(0);
++i;
}
containerStore.clear();
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
}

View file

@ -175,6 +175,9 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
if (!mEnabled && color == "#572D21")
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
if (!mEnabled)
return;
if(color != "#B29154")
{
MyGUI::UString key = mHistory->getColorTextAt(cursorPosition);
@ -227,54 +230,61 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id)
{
if (!mEnabled) return;
int separatorPos = mTopicsList->getItemCount();
int separatorPos = 0;
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
{
if (mTopicsList->getItemNameAt(i) == "")
separatorPos = i;
}
if (id > separatorPos)
if (id >= separatorPos)
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
else
{
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (topic == gmst.find("sBarter")->getString())
{
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
mWindowManager.pushGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mPtr);
}
if (topic == gmst.find("sPersuasion")->getString())
{
mPersuasionDialog.setVisible(true);
}
else if (topic == gmst.find("sSpells")->getString())
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused())
{
mWindowManager.pushGuiMode(GM_SpellBuying);
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
}
else if (topic == gmst.find("sTravel")->getString())
{
mWindowManager.pushGuiMode(GM_Travel);
mWindowManager.getTravelWindow()->startTravel(mPtr);
}
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
{
mWindowManager.pushGuiMode(GM_SpellCreation);
mWindowManager.startSpellMaking (mPtr);
}
else if (topic == gmst.find("sEnchanting")->getString())
{
mWindowManager.pushGuiMode(GM_Enchanting);
mWindowManager.startEnchanting (mPtr);
}
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
{
mWindowManager.pushGuiMode(GM_Training);
mWindowManager.startTraining (mPtr);
if (topic == gmst.find("sBarter")->getString())
{
mWindowManager.pushGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mPtr);
}
else if (topic == gmst.find("sSpells")->getString())
{
mWindowManager.pushGuiMode(GM_SpellBuying);
mWindowManager.getSpellBuyingWindow()->startSpellBuying(mPtr);
}
else if (topic == gmst.find("sTravel")->getString())
{
mWindowManager.pushGuiMode(GM_Travel);
mWindowManager.getTravelWindow()->startTravel(mPtr);
}
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
{
mWindowManager.pushGuiMode(GM_SpellCreation);
mWindowManager.startSpellMaking (mPtr);
}
else if (topic == gmst.find("sEnchanting")->getString())
{
mWindowManager.pushGuiMode(GM_Enchanting);
mWindowManager.startEnchanting (mPtr);
}
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
{
mWindowManager.pushGuiMode(GM_Training);
mWindowManager.startTraining (mPtr);
}
else if (topic == gmst.find("sRepair")->getString())
{
mWindowManager.pushGuiMode(GM_MerchantRepair);
mWindowManager.startRepair (mPtr);
}
}
}
}
@ -322,6 +332,9 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (mServices & Service_Training)
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
if (mServices & Service_Repair)
mTopicsList->addItem(gmst.find("sRepair")->getString());
if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name())
mTopicsList->addSeparator();
@ -376,10 +389,17 @@ std::string DialogueWindow::parseText(const std::string& text)
std::vector<std::string> topics;
bool hasSeparator = false;
for (unsigned int i=0; i<mTopicsList->getItemCount(); ++i)
{
if (mTopicsList->getItemNameAt(i) == "")
hasSeparator = true;
}
for(unsigned int i = 0;i<mTopicsList->getItemCount();i++)
{
std::string keyWord = mTopicsList->getItemNameAt(i);
if (separatorReached)
if (separatorReached || !hasSeparator)
topics.push_back(keyWord);
else if (keyWord == "")
separatorReached = true;

View file

@ -81,7 +81,8 @@ namespace MWGui
Service_CreateSpells = 0x04,
Service_Enchant = 0x08,
Service_Training = 0x10,
Service_Travel = 0x20
Service_Travel = 0x20,
Service_Repair = 0x40
};
protected:

View file

@ -13,6 +13,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
@ -50,6 +51,7 @@ namespace MWGui
getWidget(mFilterMisc, "MiscButton");
getWidget(mLeftPane, "LeftPane");
getWidget(mRightPane, "RightPane");
getWidget(mArmorRating, "ArmorRating");
mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
@ -288,6 +290,9 @@ namespace MWGui
mPreview.update (size.width, size.height);
mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024)));
mAvatarImage->setImageTexture("CharacterPreview");
mArmorRating->setCaptionWithReplacing ("#{sArmor}: "
+ boost::lexical_cast<std::string>(static_cast<int>(MWWorld::Class::get(mPtr).getArmorRating(mPtr))));
}
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
@ -303,7 +308,7 @@ namespace MWGui
&& (type != typeid(ESM::Ingredient).name())
&& (type != typeid(ESM::Light).name())
&& (type != typeid(ESM::Miscellaneous).name())
&& (type != typeid(ESM::Tool).name())
&& (type != typeid(ESM::Lockpick).name())
&& (type != typeid(ESM::Probe).name())
&& (type != typeid(ESM::Repair).name())
&& (type != typeid(ESM::Weapon).name())

View file

@ -9,6 +9,7 @@
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/fallback.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -138,9 +139,9 @@ namespace MWGui
std::string levelupdescription;
if(level>20)
levelupdescription=world->getFallback("Level_Up_Default");
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Default");
else
levelupdescription=world->getFallback("Level_Up_Level"+boost::lexical_cast<std::string>(level));
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Level"+boost::lexical_cast<std::string>(level));
mLevelDescription->setCaption (levelupdescription);

View file

@ -190,8 +190,8 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
markerWidget->setUserString("Caption_Text", marker.name);
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", marker.name);
markerWidget->setUserString("IsMarker", "true");
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
@ -323,16 +323,16 @@ void MapWindow::addVisitedLocation(const std::string& name, int x, int y)
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
markerWidget->setUserString("Caption_Text", name);
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
++_counter;
markerWidget = mEventBoxGlobal->createWidget<MyGUI::Button>("",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus (true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
markerWidget->setUserString("Caption_Text", name);
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
}
void MapWindow::cellExplored(int x, int y)

View file

@ -0,0 +1,132 @@
#include "merchantrepair.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "list.hpp"
#include "inventorywindow.hpp"
#include "tradewindow.hpp"
namespace MWGui
{
MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_merchantrepair.layout", parWindowManager)
{
getWidget(mList, "RepairView");
getWidget(mOkButton, "OkButton");
getWidget(mGoldLabel, "PlayerGold");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick);
}
void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
{
mActor = actor;
while (mList->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0));
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
{
if (MWWorld::Class::get(*iter).hasItemHealth(*iter))
{
int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter);
int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge;
if (maxDurability == durability)
continue;
int basePrice = MWWorld::Class::get(*iter).getValue(*iter);
float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairMult")->getFloat();
float p = std::max(1, basePrice);
float r = std::max(1, static_cast<int>(maxDurability / p));
int x = ((maxDurability - durability) / r);
x = (fRepairMult * x);
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true);
std::string name = MWWorld::Class::get(*iter).getName(*iter)
+ " - " + boost::lexical_cast<std::string>(price)
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sgp")->getString();;
MyGUI::Button* button =
mList->createWidget<MyGUI::Button>(
(price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
0,
currentY,
0,
18,
MyGUI::Align::Default
);
currentY += 18;
button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold());
button->setUserString("Price", boost::lexical_cast<std::string>(price));
button->setUserData(*iter);
button->setCaptionWithReplacing(name);
button->setSize(button->getTextSize().width,18);
button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel);
button->setUserString("ToolTipType", "ItemPtr");
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
}
}
mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
mGoldLabel->setCaptionWithReplacing("#{sGold}: "
+ boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
}
void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mList->getViewOffset().top + _rel*0.3 > 0)
mList->setViewOffset(MyGUI::IntPoint(0, 0));
else
mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3));
}
void MerchantRepair::open()
{
center();
}
void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
{
// repair
MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();
item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item);
MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
int price = boost::lexical_cast<int>(sender->getUserString("Price"));
mWindowManager.getTradeWindow()->addOrRemoveGold(-price);
startRepair(mActor);
}
void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode(GM_MerchantRepair);
}
}

View file

@ -0,0 +1,37 @@
#ifndef OPENMW_MWGUI_MERCHANTREPAIR_H
#define OPENMW_MWGUI_MERCHANTREPAIR_H
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui
{
class MerchantRepair : public WindowBase
{
public:
MerchantRepair(MWBase::WindowManager &parWindowManager);
virtual void open();
void startRepair(const MWWorld::Ptr& actor);
private:
MyGUI::ScrollView* mList;
MyGUI::Button* mOkButton;
MyGUI::TextBox* mGoldLabel;
MWWorld::Ptr mActor;
protected:
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onRepairButtonClick(MyGUI::Widget* sender);
void onOkButtonClick(MyGUI::Widget* sender);
};
}
#endif

View file

@ -16,6 +16,7 @@ namespace MWGui
GM_Scroll, // Read scroll
GM_Book, // Read book
GM_Alchemy, // Make potions
GM_Repair,
GM_Dialogue, // NPC interaction
GM_Barter,
@ -26,6 +27,7 @@ namespace MWGui
GM_SpellCreation,
GM_Enchanting,
GM_Training,
GM_MerchantRepair,
GM_Levelup,

View file

@ -0,0 +1,157 @@
#include "repair.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "widgets.hpp"
namespace MWGui
{
Repair::Repair(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_repair.layout", parWindowManager)
{
getWidget(mRepairBox, "RepairBox");
getWidget(mRepairView, "RepairView");
getWidget(mToolBox, "ToolBox");
getWidget(mToolIcon, "ToolIcon");
getWidget(mUsesLabel, "UsesLabel");
getWidget(mQualityLabel, "QualityLabel");
getWidget(mCancelButton, "CancelButton");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onCancel);
}
void Repair::open()
{
center();
}
void Repair::startRepairItem(const MWWorld::Ptr &item)
{
mRepair.setTool(item);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(item).getInventoryIcon(item);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
mToolIcon->setImageTexture (path);
mToolIcon->setUserString("ToolTipType", "ItemPtr");
mToolIcon->setUserData(item);
updateRepairView();
}
void Repair::updateRepairView()
{
MWWorld::LiveCellRef<ESM::Repair> *ref =
mRepair.getTool().get<ESM::Repair>();
int uses = (mRepair.getTool().getCellRef().mCharge != -1) ? mRepair.getTool().getCellRef().mCharge : ref->mBase->mData.mUses;
float quality = ref->mBase->mData.mQuality;
std::stringstream qualityStr;
qualityStr << std::setprecision(3) << quality;
mUsesLabel->setCaptionWithReplacing("#{sUses} " + boost::lexical_cast<std::string>(uses));
mQualityLabel->setCaptionWithReplacing("#{sQuality} " + qualityStr.str());
bool toolBoxVisible = (mRepair.getTool().getRefData().getCount() != 0);
mToolBox->setVisible(toolBoxVisible);
bool toolBoxWasVisible = (mRepairBox->getPosition().top != mToolBox->getPosition().top);
if (toolBoxVisible && !toolBoxWasVisible)
{
// shrink
mRepairBox->setPosition(mRepairBox->getPosition() + MyGUI::IntPoint(0,mToolBox->getSize().height));
mRepairBox->setSize(mRepairBox->getSize() - MyGUI::IntSize(0,mToolBox->getSize().height));
}
else if (!toolBoxVisible && toolBoxWasVisible)
{
// expand
mRepairBox->setPosition(MyGUI::IntPoint (mRepairBox->getPosition().left, mToolBox->getPosition().top));
mRepairBox->setSize(mRepairBox->getSize() + MyGUI::IntSize(0,mToolBox->getSize().height));
}
while (mRepairView->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mRepairView->getChildAt(0));
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor;
for (MWWorld::ContainerStoreIterator iter (store.begin(categories));
iter!=store.end(); ++iter)
{
if (MWWorld::Class::get(*iter).hasItemHealth(*iter))
{
int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter);
int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge;
if (maxDurability == durability)
continue;
MyGUI::TextBox* text = mRepairView->createWidget<MyGUI::TextBox> (
"SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default);
text->setCaption(MWWorld::Class::get(*iter).getName(*iter));
text->setNeedMouseFocus(false);
currentY += 19;
MyGUI::ImageBox* icon = mRepairView->createWidget<MyGUI::ImageBox> (
"ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
std::string path = std::string("icons\\");
path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
icon->setImageTexture (path);
icon->setUserString("ToolTipType", "ItemPtr");
icon->setUserData(*iter);
icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem);
icon->eventMouseWheel += MyGUI::newDelegate(this, &Repair::onMouseWheel);
Widgets::MWDynamicStatPtr chargeWidget = mRepairView->createWidget<Widgets::MWDynamicStat>
("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default);
chargeWidget->setValue(durability, maxDurability);
chargeWidget->setNeedMouseFocus(false);
currentY += 32 + 4;
}
}
mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY)));
}
void Repair::onCancel(MyGUI::Widget *sender)
{
mWindowManager.removeGuiMode(GM_Repair);
}
void Repair::onRepairItem(MyGUI::Widget *sender)
{
if (!mRepair.getTool().getRefData().getCount())
return;
mRepair.repair(*sender->getUserData<MWWorld::Ptr>());
updateRepairView();
}
void Repair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mRepairView->getViewOffset().top + _rel*0.3 > 0)
mRepairView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mRepairView->setViewOffset(MyGUI::IntPoint(0, mRepairView->getViewOffset().top + _rel*0.3));
}
}

View file

@ -0,0 +1,46 @@
#ifndef OPENMW_MWGUI_REPAIR_H
#define OPENMW_MWGUI_REPAIR_H
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwmechanics/repair.hpp"
namespace MWGui
{
class Repair : public WindowBase
{
public:
Repair(MWBase::WindowManager &parWindowManager);
virtual void open();
void startRepairItem (const MWWorld::Ptr& item);
protected:
MyGUI::Widget* mRepairBox;
MyGUI::ScrollView* mRepairView;
MyGUI::Widget* mToolBox;
MyGUI::ImageBox* mToolIcon;
MyGUI::TextBox* mUsesLabel;
MyGUI::TextBox* mQualityLabel;
MyGUI::Button* mCancelButton;
MWMechanics::Repair mRepair;
void updateRepairView();
void onRepairItem (MyGUI::Widget* sender);
void onCancel (MyGUI::Widget* sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
};
}
#endif

View file

@ -32,20 +32,9 @@ namespace MWGui
getWidget(mCancelButton, "CancelButton");
getWidget(mPlayerGold, "PlayerGold");
getWidget(mSelect, "Select");
getWidget(mSpells, "Spells");
getWidget(mSpellsView, "SpellsView");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked);
mSpells->setCoord(450/2-mSpells->getTextSize().width/2,
mSpells->getTop(),
mSpells->getTextSize().width,
mSpells->getHeight());
mSelect->setCoord(8,
mSelect->getTop(),
mSelect->getTextSize().width,
mSelect->getHeight());
}
void SpellBuyingWindow::addSpell(const std::string& spellId)

View file

@ -28,8 +28,6 @@ namespace MWGui
protected:
MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPlayerGold;
MyGUI::TextBox* mSpells;
MyGUI::TextBox* mSelect;
MyGUI::ScrollView* mSpellsView;

View file

@ -454,10 +454,13 @@ namespace MWGui
mAvailableEffectsList->clear ();
int i=0;
for (std::vector<short>::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it)
{
mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().get<ESM::GameSetting>().find(
ESM::MagicEffect::effectIdToString (*it))->getString());
mButtonMapping[i] = *it;
++i;
}
mAvailableEffectsList->adjustSize ();
@ -466,7 +469,6 @@ namespace MWGui
std::string name = MWBase::Environment::get().getWorld ()->getStore ().get<ESM::GameSetting>().find(
ESM::MagicEffect::effectIdToString (*it))->getString();
MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name);
w->setUserData(*it);
ToolTips::createMagicEffectToolTip (w, *it);
}
@ -518,7 +520,8 @@ namespace MWGui
return;
}
short effectId = *sender->getUserData<short>();
int buttonId = *sender->getUserData<int>();
short effectId = mButtonMapping[buttonId];
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{

View file

@ -88,6 +88,8 @@ namespace MWGui
protected:
std::map<int, short> mButtonMapping; // maps button ID to effect ID
Widgets::MWList* mAvailableEffectsList;
MyGUI::ScrollView* mUsedEffectsView;

View file

@ -90,7 +90,20 @@ void ToolTips::onFrame(float frameDuration)
if (mFocusObject.isEmpty ())
return;
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);
const MWWorld::Class& objectclass = MWWorld::Class::get (mFocusObject);
IntSize tooltipSize;
if ((!objectclass.hasToolTip(mFocusObject))&&(mWindowManager->getMode() == GM_Console))
{
setCoord(0, 0, 300, 300);
mDynamicToolTipBox->setVisible(true);
ToolTipInfo info;
info.caption=mFocusObject.getCellRef().mRefID;
info.icon="";
tooltipSize = createToolTip(info);
}
else
tooltipSize = getToolTipViaPtr(true);
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);

View file

@ -368,7 +368,7 @@ namespace MWGui
return services & ESM::NPC::Books;
else if (item.getTypeName() == typeid(ESM::Ingredient).name())
return services & ESM::NPC::Ingredients;
else if (item.getTypeName() == typeid(ESM::Tool).name())
else if (item.getTypeName() == typeid(ESM::Lockpick).name())
return services & ESM::NPC::Picks;
else if (item.getTypeName() == typeid(ESM::Probe).name())
return services & ESM::NPC::Probes;

View file

@ -142,7 +142,7 @@ namespace MWGui
std::string dateTimeText =
boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getDay ()) + " "
+ month + " (#{sDay} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay ()+1)
+ month + " (#{sDay} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay())
+ ") " + boost::lexical_cast<std::string>(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
mDateTimeText->setCaptionWithReplacing (dateTimeText);
@ -159,7 +159,7 @@ namespace MWGui
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(136)).mMagnitude > 0);
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();

View file

@ -55,6 +55,8 @@
#include "exposedwindow.hpp"
#include "cursor.hpp"
#include "spellicons.hpp"
#include "merchantrepair.hpp"
#include "repair.hpp"
using namespace MWGui;
@ -90,6 +92,8 @@ WindowManager::WindowManager(
, mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL)
, mTrainingWindow(NULL)
, mMerchantRepair(NULL)
, mRepair(NULL)
, mPlayerName()
, mPlayerRaceId()
, mPlayerAttributes()
@ -180,6 +184,8 @@ WindowManager::WindowManager(
mSpellCreationDialog = new SpellCreationDialog(*this);
mEnchantingDialog = new EnchantingDialog(*this);
mTrainingWindow = new TrainingWindow(*this);
mMerchantRepair = new MerchantRepair(*this);
mRepair = new Repair(*this);
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this);
mLoadingScreen->onResChange (w,h);
@ -245,6 +251,8 @@ WindowManager::~WindowManager()
delete mTrainingWindow;
delete mCountDialog;
delete mQuickKeysMenu;
delete mMerchantRepair;
delete mRepair;
delete mCursor;
cleanupGarbage();
@ -303,6 +311,8 @@ void WindowManager::updateVisible()
mSpellCreationDialog->setVisible(false);
mEnchantingDialog->setVisible(false);
mTrainingWindow->setVisible(false);
mMerchantRepair->setVisible(false);
mRepair->setVisible(false);
mHud->setVisible(mHudEnabled);
@ -428,6 +438,12 @@ void WindowManager::updateVisible()
case GM_Training:
mTrainingWindow->setVisible(true);
break;
case GM_MerchantRepair:
mMerchantRepair->setVisible(true);
break;
case GM_Repair:
mRepair->setVisible(true);
break;
case GM_InterMessageBox:
break;
case GM_Journal:
@ -1020,6 +1036,13 @@ bool WindowManager::isGuiMode() const
return !mGuiModes.empty();
}
bool WindowManager::isConsoleMode() const
{
if (mGuiModes.back()==GM_Console)
return true;
return false;
}
MWGui::GuiMode WindowManager::getMode() const
{
if (mGuiModes.empty())
@ -1125,6 +1148,16 @@ void WindowManager::startTraining(MWWorld::Ptr actor)
mTrainingWindow->startTraining(actor);
}
void WindowManager::startRepair(MWWorld::Ptr actor)
{
mMerchantRepair->startRepair(actor);
}
void WindowManager::startRepairItem(MWWorld::Ptr item)
{
mRepair->startRepairItem(item);
}
const Translation::Storage& WindowManager::getTranslationDataStorage() const
{
return mTranslationDataStorage;

View file

@ -74,6 +74,8 @@ namespace MWGui
class TrainingWindow;
class Cursor;
class SpellIcons;
class MerchantRepair;
class Repair;
class WindowManager : public MWBase::WindowManager
{
@ -102,6 +104,8 @@ namespace MWGui
virtual bool isGuiMode() const;
virtual bool isConsoleMode() const;
virtual void toggleVisible(GuiWindow wnd);
// Disallow all inventory mode windows
@ -227,6 +231,8 @@ namespace MWGui
virtual void startSpellMaking(MWWorld::Ptr actor);
virtual void startEnchanting(MWWorld::Ptr actor);
virtual void startTraining(MWWorld::Ptr actor);
virtual void startRepair(MWWorld::Ptr actor);
virtual void startRepairItem(MWWorld::Ptr item);
virtual void changePointer (const std::string& name);
@ -264,6 +270,9 @@ namespace MWGui
SpellCreationDialog* mSpellCreationDialog;
EnchantingDialog* mEnchantingDialog;
TrainingWindow* mTrainingWindow;
MerchantRepair* mMerchantRepair;
Repair* mRepair;
Translation::Storage& mTranslationDataStorage;
Cursor* mCursor;

View file

@ -55,6 +55,7 @@ namespace MWInput
, mPreviewPOVDelay(0.f)
, mTimeIdle(0.f)
, mOverencumberedMessageDelay(0.f)
, mAlwaysRunActive(false)
{
Ogre::RenderWindow* window = mOgre.getWindow ();
size_t windowHnd;
@ -180,12 +181,12 @@ namespace MWInput
break;
case A_Activate:
resetIdleTime();
activate();
if( MWBase::Environment::get().getWindowManager()->isGuiMode()
&& MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox ) {
// Pressing the activation key when a messagebox is prompting for "ok" will activate the ok button
MWBase::Environment::get().getWindowManager()->enterPressed();
}
activate();
break;
case A_Journal:
toggleJournal ();
@ -193,7 +194,7 @@ namespace MWInput
case A_AutoMove:
toggleAutoMove ();
break;
case A_ToggleWalk:
case A_AlwaysRun:
toggleWalking ();
break;
case A_ToggleWeapon:
@ -315,10 +316,10 @@ namespace MWInput
else
mPlayer.setUpDown (0);
if(actionIsActive(A_Run))
mPlayer.setRunState(true);
if (mAlwaysRunActive)
mPlayer.setRunState(!actionIsActive(A_Run));
else
mPlayer.setRunState(false);
mPlayer.setRunState(actionIsActive(A_Run));
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove)
@ -699,7 +700,7 @@ namespace MWInput
void InputManager::toggleWalking()
{
if (mWindows.isGuiMode()) return;
mPlayer.toggleRunning();
mAlwaysRunActive = !mAlwaysRunActive;
}
// Exit program now button (which is disabled in GUI mode)
@ -768,6 +769,7 @@ namespace MWInput
defaultKeyBindings[A_QuickKey10] = OIS::KC_0;
defaultKeyBindings[A_Screenshot] = OIS::KC_SYSRQ;
defaultKeyBindings[A_ToggleHUD] = OIS::KC_F12;
defaultKeyBindings[A_AlwaysRun] = OIS::KC_Y;
std::map<int, int> defaultMouseButtonBindings;
defaultMouseButtonBindings[A_Inventory] = OIS::MB_Right;
@ -834,6 +836,7 @@ namespace MWInput
descriptions[A_QuickKey8] = "sQuick8Cmd";
descriptions[A_QuickKey9] = "sQuick9Cmd";
descriptions[A_QuickKey10] = "sQuick10Cmd";
descriptions[A_AlwaysRun] = "sAlways_Run";
if (descriptions[action] == "")
return ""; // not configurable
@ -865,6 +868,7 @@ namespace MWInput
ret.push_back(A_MoveRight);
ret.push_back(A_TogglePOV);
ret.push_back(A_Run);
ret.push_back(A_AlwaysRun);
ret.push_back(A_Sneak);
ret.push_back(A_Activate);
ret.push_back(A_ToggleWeapon);

View file

@ -152,6 +152,7 @@ namespace MWInput
int mMouseWheel;
bool mDebug;
bool mUserFileExists;
bool mAlwaysRunActive;
std::map<std::string, bool> mControlSwitch;
@ -217,7 +218,7 @@ namespace MWInput
A_CycleWeaponLeft,//Cycling through weapons
A_CycleWeaponRight,
A_ToggleSneak, //Toggles Sneak
A_ToggleWalk, //Toggle Walking/Running
A_AlwaysRun, //Toggle Walking/Running
A_Sneak,
A_QuickSave,

View file

@ -71,7 +71,7 @@ namespace MWMechanics
int endurance = creatureStats.getAttribute(5).getBase();
double magickaFactor =
creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5;
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 0.5;
DynamicStat<float> health = creatureStats.getHealth();
health.setBase (static_cast<int> (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ());
@ -92,8 +92,7 @@ namespace MWMechanics
if (duration == 3600)
{
// stunted magicka
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(136)).mMagnitude > 0;
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
@ -140,9 +139,9 @@ namespace MWMechanics
for (int i=0; i<8; ++i)
{
int modifier =
creatureStats.getMagicEffects().get (EffectKey (79, i)).mMagnitude;
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyAttribute, i)).mMagnitude;
modifier -= creatureStats.getMagicEffects().get (EffectKey (17, i)).mMagnitude;
modifier -= creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::DrainAttribute, i)).mMagnitude;
creatureStats.getAttribute(i).setModifier (modifier);
}
@ -165,6 +164,9 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& ptr)
{
// erase previous death events since we are currently only tracking them while in an active cell
MWWorld::Class::get (ptr).getCreatureStats (ptr).clearHasDied();
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if(!MWWorld::Class::get(ptr).getCreatureStats(ptr).isDead())
mActors.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true)));

View file

@ -46,7 +46,7 @@ int getClosestPoint(const ESM::Pathgrid* grid,float x,float y,float z)
float m = distance(grid->mPoints[0],x,y,z);
int i0 = 0;
for(int i=1; i<grid->mPoints.size();i++)
for(unsigned int i=1; i<grid->mPoints.size();++i)
{
if(distance(grid->mPoints[i],x,y,z)<m)
{
@ -139,7 +139,7 @@ PathGridGraph buildGraph(const ESM::Pathgrid* pathgrid,float xCell = 0,float yCe
{
PathGridGraph graph;
for(int i = 0;i<pathgrid->mPoints.size();i++)
for(unsigned int i = 0;i<pathgrid->mPoints.size();++i)
{
PointID pID = boost::add_vertex(graph);
graph[pID].mX = pathgrid->mPoints[i].mX + xCell;
@ -147,7 +147,7 @@ PathGridGraph buildGraph(const ESM::Pathgrid* pathgrid,float xCell = 0,float yCe
graph[pID].mZ = pathgrid->mPoints[i].mZ;
}
for(int i = 0;i<pathgrid->mEdges.size();i++)
for(unsigned int i = 0;i<pathgrid->mEdges.size();++i)
{
PointID u = pathgrid->mEdges[i].mV0;
PointID v = pathgrid->mEdges[i].mV1;

View file

@ -2,7 +2,7 @@
#define GAME_MWMECHANICS_AITRAVEL_H
#include "aipackage.hpp"
#include "components\esm\loadpgrd.hpp"
#include <components/esm/loadpgrd.hpp>
#include <list>
namespace MWMechanics

View file

@ -10,7 +10,8 @@
namespace MWMechanics
{
CreatureStats::CreatureStats()
: mLevel (0), mLevelHealthBonus(0.f), mDead (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false),
: mLevel (0), mLevelHealthBonus(0.f), mDead (false), mDied (false), mFriendlyHits (0),
mTalkedTo (false), mAlarmed (false),
mAttacked (false), mHostile (false)
{
for (int i=0; i<4; ++i)
@ -167,7 +168,12 @@ namespace MWMechanics
mDynamic[index] = value;
if (index==0 && mDynamic[index].getCurrent()<1)
{
if (!mDead)
mDied = true;
mDead = true;
}
}
void CreatureStats::setLevel(int level)
@ -196,6 +202,16 @@ namespace MWMechanics
return mDead;
}
bool CreatureStats::hasDied() const
{
return mDied;
}
void CreatureStats::clearHasDied()
{
mDied = false;
}
void CreatureStats::resurrect()
{
if (mDead)

View file

@ -28,6 +28,7 @@ namespace MWMechanics
AiSequence mAiSequence;
float mLevelHealthBonus;
bool mDead;
bool mDied;
int mFriendlyHits;
bool mTalkedTo;
bool mAlarmed;
@ -100,6 +101,10 @@ namespace MWMechanics
bool isDead() const;
bool hasDied() const;
void clearHasDied();
void resurrect();
bool hasCommonDisease() const;

View file

@ -2,6 +2,7 @@
#include "mechanicsmanagerimp.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View file

@ -0,0 +1,110 @@
#include "repair.hpp"
#include <boost/format.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
namespace MWMechanics
{
void Repair::repair(const MWWorld::Ptr &itemToRepair)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::LiveCellRef<ESM::Repair> *ref =
mTool.get<ESM::Repair>();
// reduce number of uses left
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
mTool.getCellRef().mCharge = uses-1;
// unstack tool if required
if (mTool.getRefData().getCount() > 1 && uses == ref->mBase->mData.mUses)
{
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
MWWorld::ContainerStoreIterator it = store.add(mTool);
it->getRefData().setCount(mTool.getRefData().getCount()-1);
it->getCellRef().mCharge = -1;
mTool.getRefData().setCount(1);
}
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
float fatigueTerm = stats.getFatigueTerm();
int pcStrength = stats.getAttribute(ESM::Attribute::Strength).getModified();
int pcLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
int armorerSkill = npcStats.getSkill(ESM::Skill::Armorer).getModified();
float fRepairAmountMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairAmountMult")->getFloat();
float toolQuality = ref->mBase->mData.mQuality;
float x = (0.1 * pcStrength + 0.1 * pcLuck + armorerSkill) * fatigueTerm;
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
if (roll <= x)
{
int y = fRepairAmountMult * toolQuality * roll;
y = std::max(1, y);
// repair by 'y' points
itemToRepair.getCellRef().mCharge += y;
itemToRepair.getCellRef().mCharge = std::min(itemToRepair.getCellRef().mCharge,
MWWorld::Class::get(itemToRepair).getItemMaxHealth(itemToRepair));
// set the OnPCRepair variable on the item's script
std::string script = MWWorld::Class::get(itemToRepair).getScript(itemToRepair);
if(script != "")
itemToRepair.getRefData().getLocals().setVarByInt(script, "onpcrepair", 1);
// increase skill
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Armorer, 0);
MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1);
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairSuccess}");
}
else
{
MWBase::Environment::get().getSoundManager()->playSound("Repair Fail",1,1);
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairFailed}");
}
// tool used up?
if (mTool.getCellRef().mCharge == 0)
{
mTool.getRefData().setCount(0);
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sNotifyMessage51")->getString();
MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % MWWorld::Class::get(mTool).getName(mTool)).str());
// try to find a new tool of the same ID
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
{
if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, mTool.getCellRef().mRefID))
{
mTool = *iter;
break;
}
}
}
}
}

View file

@ -0,0 +1,23 @@
#ifndef OPENMW_MWMECHANICS_REPAIR_H
#define OPENMW_MWMECHANICS_REPAIR_H
#include "../mwworld/ptr.hpp"
namespace MWMechanics
{
class Repair
{
public:
void setTool (const MWWorld::Ptr& tool) { mTool = tool; }
MWWorld::Ptr getTool() { return mTool; }
void repair (const MWWorld::Ptr& itemToRepair);
private:
MWWorld::Ptr mTool;
};
}
#endif

View file

@ -104,11 +104,14 @@ namespace MWRender
mAnimation = new NpcAnimation(mCharacter, mNode,
MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), 0, renderHeadOnly());
float scale=1.f;
MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale);
mNode->setScale(Ogre::Vector3(scale));
mNode->setVisible (false);
Ogre::Vector3 scale = mNode->getScale();
mCamera->setPosition(mPosition * scale);
mCamera->lookAt(mLookAt * scale);
mCamera->setPosition(mPosition * mNode->getScale());
mCamera->lookAt(mLookAt * mNode->getScale());
onSetup();
}

View file

@ -85,11 +85,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
MWBase::Environment::get().getWorld()->getStore();
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
float scale = race->mData.mHeight.mMale;
if(!mNpc->isMale())
scale = race->mData.mHeight.mFemale;
node->scale(Ogre::Vector3(scale));
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHead)->mModel;
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;

View file

@ -16,16 +16,31 @@
#include "renderconst.hpp"
using namespace MWRender;
float Objects::lightLinearValue()
{
return mFallback->getFallbackFloat("LightAttenuation_LinearValue");
}
float Objects::lightLinearRadiusMult()
{
return mFallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
}
float Objects::lightQuadraticValue()
{
return mFallback->getFallbackFloat("LightAttenuation_QuadraticValue");
}
float Objects::lightQuadraticRadiusMult()
{
return mFallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
}
/// \todo Replace these, once fallback values from the ini file are available.
float Objects::lightLinearValue = 3;
float Objects::lightLinearRadiusMult = 1;
float Objects::lightQuadraticValue = 16;
float Objects::lightQuadraticRadiusMult = 1;
bool Objects::lightOutQuadInLin = true;
bool Objects::lightQuadratic = false;
bool Objects::lightOutQuadInLin()
{
return mFallback->getFallbackBool("LightAttenuation_OutQuadInLin");
}
bool Objects::lightQuadratic()
{
return mFallback->getFallbackBool("LightAttenuation_UseQuadratic");
}
int Objects::uniqueID = 0;
@ -269,14 +284,14 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre
if (!quadratic)
{
float r = radius * lightLinearRadiusMult;
float attenuation = lightLinearValue / r;
float r = radius * lightLinearRadiusMult();
float attenuation = lightLinearValue() / r;
light->setAttenuation(r*10, 0, attenuation, 0);
}
else
{
float r = radius * lightQuadraticRadiusMult;
float attenuation = lightQuadraticValue / pow(r, 2);
float r = radius * lightQuadraticRadiusMult();
float attenuation = lightQuadraticValue() / pow(r, 2);
light->setAttenuation(r*10, 0, 0, attenuation);
}

View file

@ -5,6 +5,7 @@
#include <OgreAxisAlignedBox.h>
#include <openengine/ogre/renderer.hpp>
#include "../mwworld/fallback.hpp"
namespace MWWorld
{
@ -56,21 +57,21 @@ class Objects{
Ogre::SceneNode* mRootNode;
bool mIsStatic;
static int uniqueID;
MWWorld::Fallback* mFallback;
float lightLinearValue();
float lightLinearRadiusMult();
static float lightLinearValue;
static float lightLinearRadiusMult;
bool lightQuadratic();
float lightQuadraticValue();
float lightQuadraticRadiusMult();
static bool lightQuadratic;
static float lightQuadraticValue;
static float lightQuadraticRadiusMult;
static bool lightOutQuadInLin;
bool lightOutQuadInLin();
void clearSceneNode (Ogre::SceneNode *node);
///< Remove all movable objects from \a node.
public:
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mIsStatic(false) {}
Objects(OEngine::Render::OgreRenderer& renderer, MWWorld::Fallback* fallback): mRenderer (renderer), mIsStatic(false), mFallback(fallback) {}
~Objects(){}
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool light=false);

View file

@ -48,9 +48,10 @@ using namespace Ogre;
namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir,
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine)
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine,MWWorld::Fallback* fallback)
: mRendering(_rend)
, mObjects(mRendering)
, mFallback(fallback)
, mObjects(mRendering,mFallback)
, mActors(mRendering, this)
, mAmbientMode(0)
, mSunEnabled(0)
@ -884,6 +885,8 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)
mPlayer->setAnimation(anim);
mWater->removeEmitter (ptr);
mWater->addEmitter (ptr);
// apply race height
MWBase::Environment::get().getWorld()->scaleObject(ptr, 1.f);
}
void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw)

View file

@ -60,7 +60,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
public:
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir,
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine);
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine,MWWorld::Fallback* fallback);
virtual ~RenderingManager();
void togglePOV() {
@ -220,6 +220,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
bool mSunEnabled;
MWWorld::Fallback* mFallback;
SkyManager* mSkyManager;
OcclusionQuery* mOcclusionQuery;

View file

@ -21,6 +21,8 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/fallback.hpp"
#include "renderconst.hpp"
#include "renderingmanager.hpp"
@ -266,11 +268,12 @@ void SkyManager::create()
mLightning->setVisible (false);
mLightning->setDiffuseColour (ColourValue(3,3,3));
mSecunda = new Moon("secunda_texture", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
mSecunda = new Moon("secunda_texture", /*0.5*/fallback->getFallbackFloat("Moons_Secunda_Size")/100, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
mSecunda->setType(Moon::Type_Secunda);
mSecunda->setRenderQueue(RQG_SkiesEarly+4);
mMasser = new Moon("masser_texture", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
mMasser = new Moon("masser_texture", /*0.75*/fallback->getFallbackFloat("Moons_Masser_Size")/100, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
mMasser->setRenderQueue(RQG_SkiesEarly+3);
mMasser->setType(Moon::Type_Masser);
@ -368,7 +371,7 @@ int SkyManager::getSecundaPhase() const
void SkyManager::update(float duration)
{
if (!mEnabled) return;
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
mCamera->getParentSceneNode ()->needUpdate ();
mRootNode->setPosition(mCamera->getDerivedPosition());
@ -381,7 +384,7 @@ void SkyManager::update(float duration)
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
mSecunda->setColour ( mMoonRed ? ColourValue(1.0, 0.0784, 0.0784) : ColourValue(1,1,1,1));
mSecunda->setColour ( mMoonRed ? fallback->getFallbackColour("Moons_Script_Color") : ColourValue(1,1,1,1));
mMasser->setColour (ColourValue(1,1,1,1));
if (mSunEnabled)

View file

@ -59,7 +59,7 @@ namespace MWScript
store.get<ESM::CreatureLevList>().search (name) ||
store.get<ESM::ItemLevList>().search (name) ||
store.get<ESM::Light>().search (name) ||
store.get<ESM::Tool>().search (name) ||
store.get<ESM::Lockpick>().search (name) ||
store.get<ESM::Miscellaneous>().search (name) ||
store.get<ESM::NPC>().search (name) ||
store.get<ESM::Probe>().search (name) ||

View file

@ -315,5 +315,6 @@ op 0x20001f8: Drop
op 0x20001f9: Drop, explicit reference
op 0x20001fa: DropSoulGem
op 0x20001fb: DropSoulGem, explicit reference
op 0x20001fc: OnDeath
opcodes 0x20001fa-0x3ffffff unused
opcodes 0x20001fd-0x3ffffff unused

View file

@ -215,19 +215,22 @@ namespace MWScript
std::string InterpreterContext::getNPCRace() const
{
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
return npc.mRace;
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npc.mRace);
return race->mName;
}
std::string InterpreterContext::getNPCClass() const
{
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
return npc.mClass;
const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(npc.mClass);
return class_->mName;
}
std::string InterpreterContext::getNPCFaction() const
{
ESM::NPC npc = *mReference.get<ESM::NPC>()->mBase;
return npc.mFaction;
const ESM::Faction* faction = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(npc.mFaction);
return faction->mName;
}
std::string InterpreterContext::getNPCRank() const

View file

@ -1025,6 +1025,27 @@ namespace MWScript
}
};
class OpOnDeath : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWScript::InterpreterContext& context
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
MWWorld::Ptr ptr = context.getReference();
Interpreter::Type_Integer value =
MWWorld::Class::get (ptr).getCreatureStats (ptr).hasDied();
if (value)
MWWorld::Class::get (ptr).getCreatureStats (ptr).clearHasDied();
runtime.push (value);
}
};
const int numberOfAttributes = 8;
const int opcodeGetAttribute = 0x2000027;
@ -1114,6 +1135,8 @@ namespace MWScript
const int opcodeLowerRank = 0x20001ea;
const int opcodeLowerRankExplicit = 0x20001eb;
const int opcodeOnDeath = 0x20001fc;
void registerExtensions (Compiler::Extensions& extensions)
{
static const char *attributes[numberOfAttributes] =
@ -1227,6 +1250,8 @@ namespace MWScript
extensions.registerInstruction ("pcclearexpelled", "/S", opcodePcClearExpelled, opcodePcClearExpelledExplicit);
extensions.registerInstruction ("raiserank", "", opcodeRaiseRank, opcodeRaiseRankExplicit);
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -1341,6 +1366,8 @@ namespace MWScript
interpreter.installSegment5 (opcodeRaiseRankExplicit, new OpRaiseRank<ExplicitRef>);
interpreter.installSegment5 (opcodeLowerRank, new OpLowerRank<ImplicitRef>);
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath);
}
}
}

View file

@ -0,0 +1,18 @@
#include "actionrepair.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
namespace MWWorld
{
ActionRepair::ActionRepair(const Ptr &item)
: Action(false, item)
{
}
void ActionRepair::executeImp (const Ptr& actor)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair);
MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget());
}
}

View file

@ -0,0 +1,17 @@
#ifndef GAME_MWWORLD_ACTIONREPAIR_H
#define GAME_MWWORLD_ACTIONREPAIR_H
#include "action.hpp"
namespace MWWorld
{
class ActionRepair : public Action
{
virtual void executeImp (const Ptr& actor);
public:
ActionRepair(const MWWorld::Ptr& item);
};
}
#endif

View file

@ -206,7 +206,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
if (MWWorld::LiveCellRef<ESM::Light> *ref = cell.mLights.find (name))
ptr = Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Tool> *ref = cell.mLockpicks.find (name))
if (MWWorld::LiveCellRef<ESM::Lockpick> *ref = cell.mLockpicks.find (name))
ptr = Ptr (ref, &cell);
if (MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = cell.mMiscItems.find (name))

Some files were not shown because too many files have changed in this diff Show more