1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 06:23:52 +00:00
This commit is contained in:
Marek Kochanowicz 2014-01-14 09:36:29 +01:00
commit a81d9c23f8
285 changed files with 5762 additions and 3137 deletions

3
.gitignore vendored
View file

@ -3,7 +3,6 @@ CMakeFiles
*/CMakeFiles
CMakeCache.txt
cmake_install.cmake
CMakeLists.txt.user
Makefile
makefile
build
@ -22,6 +21,8 @@ Doxygen
.project
.settings
.directory
## qt-creator
CMakeLists.txt.user*
## resources
data

View file

@ -15,7 +15,7 @@ before_install:
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
- sudo apt-get install -qq libbullet-dev libogre-1.8-dev libmygui-dev libsdl2-dev libunshield-dev
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
- sudo mkdir /usr/src/gtest/build
- cd /usr/src/gtest/build
- sudo cmake .. -DBUILD_SHARED_LIBS=1

View file

@ -99,8 +99,6 @@ set(OENGINE_BULLET
${LIBDIR}/openengine/bullet/BtOgreExtras.h
${LIBDIR}/openengine/bullet/BtOgreGP.h
${LIBDIR}/openengine/bullet/BtOgrePG.h
${LIBDIR}/openengine/bullet/CMotionState.cpp
${LIBDIR}/openengine/bullet/CMotionState.h
${LIBDIR}/openengine/bullet/physic.cpp
${LIBDIR}/openengine/bullet/physic.hpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
@ -185,6 +183,9 @@ if (WIN32)
set(Boost_USE_STATIC_LIBS ON)
set(PLATFORM_INCLUDE_DIR "platform")
add_definitions(-DBOOST_ALL_NO_LIB)
# Suppress WinMain(), provided by SDL
add_definitions(-DSDL_MAIN_HANDLED)
else (WIN32)
set(PLATFORM_INCLUDE_DIR "")
find_path (UUID_INCLUDE_DIR uuid/uuid.h)
@ -212,7 +213,7 @@ if (HAVE_UNORDERED_MAP)
endif ()
set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)
set(BOOST_COMPONENTS system filesystem program_options)
IF(BOOST_STATIC)
set(Boost_USE_STATIC_LIBS ON)

View file

@ -717,16 +717,26 @@ std::string landFlags(int flags)
return properties;
}
std::string leveledListFlags(int flags)
std::string itemListFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::LeveledListBase::AllLevels) properties += "AllLevels ";
// This flag apparently not present on creature lists...
if (flags & ESM::LeveledListBase::Each) properties += "Each ";
if (flags & ESM::ItemLevList::AllLevels) properties += "AllLevels ";
if (flags & ESM::ItemLevList::Each) properties += "Each ";
int unused = (0xFFFFFFFF ^
(ESM::LeveledListBase::AllLevels|
ESM::LeveledListBase::Each));
(ESM::ItemLevList::AllLevels|
ESM::ItemLevList::Each));
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
}
std::string creatureListFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels ";
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;
@ -764,34 +774,19 @@ std::string magicEffectFlags(int flags)
{
std::string properties = "";
if (flags == 0) properties += "[None] ";
// Enchanting & SpellMaking occur on the same list of effects.
// "EXTRA SPELL" appears in the construction set under both the
// spell making and enchanting tabs as an allowed effect. Since
// most of the effects without this flags are defective in various
// ways, it's still very unclear what these flag bits are.
if (flags & ESM::MagicEffect::SpellMaking) properties += "SpellMaking ";
if (flags & ESM::MagicEffect::Enchanting) properties += "Enchanting ";
if (flags & 0x00000040) properties += "RangeNoSelf ";
if (flags & 0x00000080) properties += "RangeTouch ";
if (flags & 0x00000100) properties += "RangeTarget ";
if (flags & 0x00001000) properties += "Unknown2 ";
if (flags & 0x00000001) properties += "AffectSkill ";
if (flags & 0x00000002) properties += "AffectAttribute ";
if (flags & ESM::MagicEffect::TargetAttribute) properties += "TargetAttribute ";
if (flags & ESM::MagicEffect::TargetSkill) properties += "TargetSkill ";
if (flags & ESM::MagicEffect::NoDuration) properties += "NoDuration ";
if (flags & 0x00000008) properties += "NoMagnitude ";
if (flags & 0x00000010) properties += "Negative ";
if (flags & 0x00000020) properties += "Unknown1 ";
// ESM componet says 0x800 is negative, but none of the magic
// effects have this flags set.
if (flags & ESM::MagicEffect::Negative) properties += "Unused ";
// Since only Chameleon has this flag it could be anything
// that uniquely distinguishes Chameleon.
if (flags & 0x00002000) properties += "Chameleon ";
if (flags & 0x00004000) properties += "Bound ";
if (flags & 0x00008000) properties += "Summon ";
// Calm, Demoralize, Frenzy, Lock, Open, Rally, Soultrap, Turn Unded
if (flags & 0x00010000) properties += "Unknown3 ";
if (flags & 0x00020000) properties += "Absorb ";
if (flags & ESM::MagicEffect::NoMagnitude) properties += "NoMagnitude ";
if (flags & ESM::MagicEffect::Harmful) properties += "Harmful ";
if (flags & ESM::MagicEffect::ContinuousVfx) properties += "ContinuousVFX ";
if (flags & ESM::MagicEffect::CastSelf) properties += "CastSelf ";
if (flags & ESM::MagicEffect::CastTouch) properties += "CastTouch ";
if (flags & ESM::MagicEffect::CastTarget) properties += "CastTarget ";
if (flags & ESM::MagicEffect::UncappedDamage) properties += "UncappedDamage ";
if (flags & ESM::MagicEffect::NonRecastable) properties += "NonRecastable ";
if (flags & ESM::MagicEffect::Unreflectable) properties += "Unreflectable ";
if (flags & ESM::MagicEffect::CasterLinked) properties += "CasterLinked ";
if (flags & 0xFFFC0000) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags);
return properties;

View file

@ -50,7 +50,8 @@ std::string cellFlags(int flags);
std::string containerFlags(int flags);
std::string creatureFlags(int flags);
std::string landFlags(int flags);
std::string leveledListFlags(int flags);
std::string creatureListFlags(int flags);
std::string itemListFlags(int flags);
std::string lightFlags(int flags);
std::string magicEffectFlags(int flags);
std::string npcFlags(int flags);

View file

@ -13,8 +13,8 @@ void printAIPackage(ESM::AIPackage p)
std::cout << " Distance: " << p.mWander.mDistance << std::endl;
std::cout << " Duration: " << p.mWander.mDuration << std::endl;
std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl;
if (p.mWander.mUnk != 1)
std::cout << " Unknown: " << (int)p.mWander.mUnk << std::endl;
if (p.mWander.mShouldRepeat != 1)
std::cout << " Should repeat: " << (bool)p.mWander.mShouldRepeat << std::endl;
std::cout << " Idle: ";
for (int i = 0; i != 8; i++)
@ -834,7 +834,8 @@ template<>
void Record<ESM::CreatureLevList>::print()
{
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
std::cout << " Flags: " << leveledListFlags(mData.mFlags) << std::endl;
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Chance none: " << mData.mChanceNone << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
@ -846,11 +847,12 @@ template<>
void Record<ESM::ItemLevList>::print()
{
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
std::cout << " Flags: " << leveledListFlags(mData.mFlags) << std::endl;
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Chance none: " << mData.mChanceNone << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
std::cout << " Inventory: Count: " << iit->mLevel
std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl;
}

View file

@ -137,8 +137,3 @@ if (BUILD_WITH_CODE_COVERAGE)
target_link_libraries(omwlauncher gcov)
endif()
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
if (UNIX AND NOT APPLE)
target_link_libraries(omwlauncher dl Xt)
endif()

View file

@ -16,6 +16,7 @@
int main(int argc, char *argv[])
{
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
SDL_SetMainReady();
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
qDebug() << "SDL_Init failed: " << QString::fromStdString(SDL_GetError());

View file

@ -219,7 +219,7 @@ bool Launcher::MainDialog::showFirstRunDialog()
}
// Create the file if it doesn't already exist, else the importer will fail
QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg");
QString path = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + QString("openmw.cfg");
QFile file(path);
if (!file.exists()) {
@ -334,7 +334,7 @@ bool Launcher::MainDialog::setupLauncherSettings()
{
mLauncherSettings.setMultiValueEnabled(true);
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
QStringList paths;
paths.append(QString("launcher.cfg"));
@ -440,7 +440,7 @@ bool Launcher::expansions(Launcher::UnshieldThread& cd)
bool Launcher::MainDialog::setupGameSettings()
{
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
// Load the user config file first, separately
@ -591,7 +591,7 @@ bool Launcher::MainDialog::setupGraphicsSettings()
{
mGraphicsSettings.setMultiValueEnabled(false);
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
QFile localDefault(QString("settings-default.cfg"));
@ -678,7 +678,7 @@ bool Launcher::MainDialog::writeSettings()
mGraphicsPage->saveSettings();
mDataFilesPage->saveSettings();
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
QDir dir(userPath);
if (!dir.exists()) {

View file

@ -16,7 +16,7 @@ MwIniImporter::MwIniImporter()
const char *map[][2] =
{
{ "fps", "General:Show FPS" },
{ "nosound", "General:Disable Audio" },
{ "no-sound", "General:Disable Audio" },
{ 0, 0 }
};
const char *fallback[] = {

View file

@ -143,7 +143,7 @@ if(WIN32)
set(QT_USE_QTMAIN TRUE)
endif(WIN32)
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtXml QtXmlPatterns REQUIRED)
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
include(${QT_USE_FILE})
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})

View file

@ -86,10 +86,6 @@ void CS::Editor::setupDataFiles()
return;
}
// Set the charset for reading the esm/esp files
// QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
//mFileDialog.setEncoding(encoding);
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());

View file

@ -42,10 +42,10 @@ int main(int argc, char *argv[])
// TODO: Ogre startup shouldn't be here, but it currently has to:
// SceneWidget destructor will delete the created render window, which would be called _after_ Root has shut down :(
OgreInit::OgreInit ogreInit;
ogreInit.init("./opencsOgre.log"); // TODO log path?
Application mApplication (argc, argv);
OgreInit::OgreInit ogreInit;
ogreInit.init("./opencsOgre.log"); // TODO log path?
#ifdef Q_OS_MAC
QDir dir(QCoreApplication::applicationDirPath());

View file

@ -2221,7 +2221,7 @@ void CSMDoc::Document::createBase()
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
mProjectPath ((configuration.getUserPath() / "projects") /
mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath)
{
@ -2254,7 +2254,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co
}
else
{
boost::filesystem::path locCustomFiltersPath (configuration.getUserPath());
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
locCustomFiltersPath /= "defaultfilters";
if (boost::filesystem::exists(locCustomFiltersPath))

View file

@ -15,7 +15,7 @@
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
: mConfiguration (configuration)
{
boost::filesystem::path projectPath = configuration.getUserPath() / "projects";
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
if (!boost::filesystem::is_directory (projectPath))
boost::filesystem::create_directories (projectPath);
@ -53,4 +53,4 @@ bool CSMDoc::DocumentManager::removeDocument (Document *document)
void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir)
{
mResDir = boost::filesystem::system_complete(parResDir);
}
}

View file

@ -251,7 +251,7 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName)
bool localOk = loadFromFile(localFilePath);
//user
mUserFilePath = QString::fromStdString(mCfgMgr.getUserPath().string()) + fileName;
mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName;
loadFromFile(mUserFilePath);
if (!(localOk || globalOk))

View file

@ -263,7 +263,7 @@ namespace
static const char *sCreatureTypes[] =
{
"Creature", "Deadra", "Undead", "Humanoid", 0
"Creature", "Daedra", "Undead", "Humanoid", 0
};
static const char *sWeaponTypes[] =
@ -342,4 +342,4 @@ std::vector<std::string> CSMWorld::Columns::getEnums (ColumnId column)
}
return enums;
}
}

View file

@ -6,6 +6,7 @@
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreEntity.h>
#include <OgreCamera.h>
namespace CSVRender
{

View file

@ -19,8 +19,8 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
actors objects renderinginterface localmap occlusionquery water shadows
characterpreview externalrendering globalmap videoplayer ripplesimulation refraction
terrainstorage
characterpreview globalmap videoplayer ripplesimulation refraction
terrainstorage renderconst
)
add_openmw_dir (mwinput
@ -74,6 +74,7 @@ add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
disease pickpocket levelledlist
)
add_openmw_dir (mwbase
@ -82,6 +83,8 @@ add_openmw_dir (mwbase
)
# Main executable
set(BOOST_COMPONENTS system filesystem program_options thread wave)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
IF(OGRE_STATIC)
ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
@ -111,6 +114,7 @@ add_definitions(${SOUND_DEFINE})
target_link_libraries(openmw
${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
${SHINY_LIBRARIES}
${Boost_LIBRARIES}
${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY}
@ -118,7 +122,6 @@ target_link_libraries(openmw
${MYGUI_LIBRARIES}
${SDL2_LIBRARY}
${MYGUI_PLATFORM_LIBRARIES}
${SHINY_LIBRARIES}
"oics"
"sdl4ogre"
components
@ -137,12 +140,6 @@ if (UNIX AND NOT APPLE)
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
endif()
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
if (UNIX AND NOT APPLE)
target_link_libraries(openmw dl Xt)
endif()
if(APPLE)
find_library(COCOA_FRAMEWORK Cocoa)
find_library(IOKIT_FRAMEWORK IOKit)

View file

@ -6,6 +6,7 @@
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/ucontext.h>
#include <sys/utsname.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
@ -42,78 +43,78 @@ static char altstack[SIGSTKSZ];
static struct {
int signum;
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[1024];
int signum;
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[1024];
} crash_info;
static const struct {
const char *name;
int signum;
const char *name;
int signum;
} signals[] = {
{ "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS },
{ NULL, 0 }
{ "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS },
{ NULL, 0 }
};
static const struct {
int code;
const char *name;
int code;
const char *name;
} sigill_codes[] = {
#ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" },
#endif
{ 0, NULL }
#ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
int code;
const char *name;
} sigfpe_codes[] = {
{ FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL }
{ FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL }
};
static const struct {
int code;
const char *name;
int code;
const char *name;
} sigsegv_codes[] = {
#ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif
{ 0, NULL }
#ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
int code;
const char *name;
} sigbus_codes[] = {
#ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" },
#endif
{ 0, NULL }
#ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" },
#endif
{ 0, NULL }
};
static int (*cc_user_info)(char*, char*);
@ -121,314 +122,318 @@ static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid)
{
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
/* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{
fprintf(f, "attach %d\n"
"shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n"
"shell echo \"\"\n"
"shell echo \"* Threads\"\n"
"info threads\n"
"shell echo \"\"\n"
"shell echo \"* FPU Status\"\n"
"info float\n"
"shell echo \"\"\n"
"shell echo \"* Registers\"\n"
"info registers\n"
"shell echo \"\"\n"
"shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n"
"detach\n"
"quit\n", pid);
fclose(f);
/* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{
fprintf(f, "attach %d\n"
"shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n"
"shell echo \"\"\n"
"shell echo \"* Threads\"\n"
"info threads\n"
"shell echo \"\"\n"
"shell echo \"* FPU Status\"\n"
"info float\n"
"shell echo \"\"\n"
"shell echo \"* Registers\"\n"
"info registers\n"
"shell echo \"\"\n"
"shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n"
"detach\n"
"quit\n", pid);
fclose(f);
/* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);
/* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);
system(cmd_buf);
/* Clean up */
remove(respfile);
}
else
{
/* Error creating temp file */
if(fd >= 0)
{
close(fd);
remove(respfile);
}
printf("!!! Could not create gdb command file\n");
}
fflush(stdout);
system(cmd_buf);
/* Clean up */
remove(respfile);
}
else
{
/* Error creating temp file */
if(fd >= 0)
{
close(fd);
remove(respfile);
}
printf("!!! Could not create gdb command file\n");
}
fflush(stdout);
}
static void sys_info(void)
{
#ifdef __unix__
system("echo \"System: `uname -a`\"");
putchar('\n');
fflush(stdout);
struct utsname info;
if(uname(&info))
printf("!!! Failed to get system information\n");
else
printf("System: %s %s %s %s %s\n",
info.sysname, info.nodename, info.release, info.version, info.machine);
fflush(stdout);
#endif
}
static size_t safe_write(int fd, const void *buf, size_t len)
{
size_t ret = 0;
while(ret < len)
{
ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{
if(errno == EINTR)
continue;
break;
}
ret += rem;
}
return ret;
size_t ret = 0;
while(ret < len)
{
ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{
if(errno == EINTR)
continue;
break;
}
ret += rem;
}
return ret;
}
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
//ucontext_t *ucontext = (ucontext_t*)context;
pid_t dbg_pid;
int fd[2];
pid_t dbg_pid;
int fd[2];
/* Make sure the effective uid is the real uid */
if(getuid() != geteuid())
{
raise(signum);
return;
}
/* Make sure the effective uid is the real uid */
if(getuid() != geteuid())
{
raise(signum);
return;
}
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1)
{
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum);
return;
}
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1)
{
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum);
return;
}
crash_info.signum = signum;
crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo;
if(siginfo)
crash_info.siginfo = *siginfo;
if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
crash_info.signum = signum;
crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo;
if(siginfo)
crash_info.siginfo = *siginfo;
if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
/* Fork off to start a crash handler */
switch((dbg_pid=fork()))
{
/* Error */
case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum);
return;
/* Fork off to start a crash handler */
switch((dbg_pid=fork()))
{
/* Error */
case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum);
return;
case 0:
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
case 0:
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execl(argv0, argv0, crash_switch, NULL);
execl(argv0, argv0, crash_switch, NULL);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1);
default:
default:
#ifdef __linux__
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]);
close(fd[1]);
safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]);
close(fd[1]);
/* Wait; we'll be killed when gdb is done */
do {
int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status)))
{
/* The debug process died before it could kill us */
raise(signum);
break;
}
} while(1);
}
/* Wait; we'll be killed when gdb is done */
do {
int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status)))
{
/* The debug process died before it could kill us */
raise(signum);
break;
}
} while(1);
}
}
static void crash_handler(const char *logfile)
{
const char *sigdesc = "";
const char *sigdesc = "";
int i;
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1);
}
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1);
}
/* Get the signal description */
for(i = 0;signals[i].name;++i)
{
if(signals[i].signum == crash_info.signum)
{
sigdesc = signals[i].name;
break;
}
}
/* Get the signal description */
for(i = 0;signals[i].name;++i)
{
if(signals[i].signum == crash_info.signum)
{
sigdesc = signals[i].name;
break;
}
}
if(crash_info.has_siginfo)
{
switch(crash_info.signum)
{
case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i)
{
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigsegv_codes[i].name;
break;
}
}
break;
if(crash_info.has_siginfo)
{
switch(crash_info.signum)
{
case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i)
{
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigsegv_codes[i].name;
break;
}
}
break;
case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i)
{
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigfpe_codes[i].name;
break;
}
}
break;
case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i)
{
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigfpe_codes[i].name;
break;
}
}
break;
case SIGILL:
for(i = 0;sigill_codes[i].name;++i)
{
if(sigill_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigill_codes[i].name;
break;
}
}
break;
case SIGILL:
for(i = 0;sigill_codes[i].name;++i)
{
if(sigill_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigill_codes[i].name;
break;
}
}
break;
case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i)
{
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigbus_codes[i].name;
break;
}
}
break;
}
}
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr);
case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i)
{
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigbus_codes[i].name;
break;
}
}
break;
}
}
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr);
if(logfile)
{
/* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout)
{
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1);
}
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
if(logfile)
{
/* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout)
{
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1);
}
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout);
fflush(stdout);
}
printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout);
fflush(stdout);
}
sys_info();
sys_info();
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf);
fflush(stdout);
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf);
fflush(stdout);
if(crash_info.pid > 0)
{
gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL);
}
if(crash_info.pid > 0)
{
gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL);
}
if(logfile)
{
if(logfile)
{
char cwd[MAXPATHLEN];
getcwd(cwd, MAXPATHLEN);
std::string message = "OpenMW has encountered a fatal error.\nCrash log saved to '" + std::string(cwd) + "/" + std::string(logfile) + "'.\n Please report this to https://bugs.openmw.org !";
SDL_ShowSimpleMessageBox(0, "Fatal Error", message.c_str(), NULL);
}
exit(0);
}
exit(0);
}
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
{
struct sigaction sa;
stack_t altss;
int retval;
struct sigaction sa;
stack_t altss;
int retval;
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile);
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile);
cc_user_info = user_info;
cc_user_info = user_info;
if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else
{
getcwd(argv0, sizeof(argv0));
retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
}
if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else
{
getcwd(argv0, sizeof(argv0));
retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
}
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */
altss.ss_sp = altstack;
altss.ss_flags = 0;
altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL);
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */
altss.ss_sp = altstack;
altss.ss_flags = 0;
altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
retval = 0;
while(num_signals--)
{
retval = 0;
while(num_signals--)
{
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE && *signals != SIGABRT &&
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{
*signals = 0;
retval = -1;
}
++signals;
}
return retval;
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{
*signals = 0;
retval = -1;
}
++signals;
}
return retval;
}

View file

@ -65,10 +65,6 @@ void OMW::Engine::executeLocalScripts()
localScripts.setIgnore (MWWorld::Ptr());
}
void OMW::Engine::setAnimationVerbose(bool animverbose)
{
}
bool OMW::Engine::frameStarted (const Ogre::FrameEvent& evt)
{
bool paused = MWBase::Environment::get().getWindowManager()->isGuiMode();
@ -161,6 +157,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
//kindly ask SDL not to trash our OGL context
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
SDL_SetMainReady();
if(SDL_Init(flags) != 0)
{
throw std::runtime_error("Could not initialize SDL! " + std::string(SDL_GetError()));
@ -301,7 +298,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
// load user settings if they exist, otherwise just load the default settings as user settings
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
const std::string settingspath = mCfgMgr.getUserConfigPath().string() + "/settings.cfg";
if (boost::filesystem::exists(settingspath))
settings.loadUser(settingspath);
else if (boost::filesystem::exists(localdefault))
@ -313,12 +310,16 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
// load nif overrides
NifOverrides::Overrides nifOverrides;
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg"))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg");
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
settings.setBool("hardware cursors", "GUI", true);
std::string transparencyOverrides = "/transparency-overrides.cfg";
std::string materialOverrides = "/material-overrides.cfg";
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + transparencyOverrides))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + transparencyOverrides);
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + transparencyOverrides))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + transparencyOverrides);
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + materialOverrides))
nifOverrides.loadMaterialOverrides(mCfgMgr.getLocalPath().string() + materialOverrides);
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + materialOverrides))
nifOverrides.loadMaterialOverrides(mCfgMgr.getGlobalPath().string() + materialOverrides);
return settingspath;
}
@ -373,7 +374,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so
std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input.xml").string();
bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab);
mEnvironment.setInputManager (input);
@ -511,13 +512,13 @@ void OMW::Engine::activate()
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
boost::shared_ptr<MWWorld::Action> action =
MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
MWWorld::Class::get (ptr).activate (ptr, MWBase::Environment::get().getWorld()->getPlayerPtr());
interpreterContext.activate (ptr, action);
std::string script = MWWorld::Class::get (ptr).getScript (ptr);
MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayerPtr());
if (!script.empty())
{
@ -536,7 +537,7 @@ void OMW::Engine::screenshot()
// Count screenshots.
int shotCount = 0;
const std::string screenshotPath = mCfgMgr.getUserPath().string();
const std::string& screenshotPath = mCfgMgr.getUserDataPath().string();
// Find the first unused filename with a do-while
std::ostringstream stream;

View file

@ -171,8 +171,6 @@ namespace OMW
/// Font encoding
void setEncoding(const ToUTF8::FromType& encoding);
void setAnimationVerbose(bool animverbose);
void setFallbackValues(std::map<std::string,std::string> map);
/// Enable console-only script functionality

View file

@ -11,6 +11,7 @@
#include <boost/iostreams/stream_buffer.hpp>
// For OutputDebugString
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// makes __argc and __argv available on windows
#include <cstdlib>
@ -121,10 +122,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon")
("anim-verbose", bpo::value<bool>()->implicit_value(true)
->default_value(false), "output animation indices files")
("nosound", bpo::value<bool>()->implicit_value(true)
("no-sound", bpo::value<bool>()->implicit_value(true)
->default_value(false), "disable all sounds")
("script-verbose", bpo::value<bool>()->implicit_value(true)
@ -168,8 +166,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
bpo::store(valid_opts, variables);
bpo::notify(variables);
cfgMgr.readConfiguration(variables, desc);
bool run = true;
if (variables.count ("help"))
@ -187,6 +183,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
if (!run)
return false;
cfgMgr.readConfiguration(variables, desc);
engine.setGrabMouse(!variables.count("no-grab"));
// Font encoding settings
@ -237,10 +235,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setNewGame(variables["new-game"].as<bool>());
// other settings
engine.setSoundUsage(!variables["nosound"].as<bool>());
engine.setSoundUsage(!variables["no-sound"].as<bool>());
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
engine.setCompileAll(variables["script-all"].as<bool>());
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
engine.setScriptConsoleMode (variables["script-console"].as<bool>());
engine.setStartupScript (variables["script-run"].as<std::string>());

View file

@ -51,7 +51,7 @@ namespace MWBase
virtual void persuade (int type) = 0;
virtual int getTemporaryDispositionChange () const = 0;
virtual void applyTemporaryDispositionChange (int delta) = 0;
virtual void applyDispositionChange (int delta) = 0;
};
}

View file

@ -141,15 +141,15 @@ void MWBase::Environment::cleanup()
delete mScriptManager;
mScriptManager = 0;
delete mWindowManager;
mWindowManager = 0;
delete mWorld;
mWorld = 0;
delete mSoundManager;
mSoundManager = 0;
delete mWindowManager;
mWindowManager = 0;
delete mInputManager;
mInputManager = 0;
}

View file

@ -76,8 +76,12 @@ namespace MWBase
virtual void setPlayerClass (const ESM::Class& class_) = 0;
///< Set player class to custom class.
virtual void restoreDynamicStats() = 0;
///< If the player is sleeping, this should be called every hour.
virtual void rest(bool sleep) = 0;
///< If the player is sleeping or waiting, this should be called every hour.
/// @param sleep is the player sleeping or waiting?
virtual int getHoursToRest() const = 0;
///< Calculate how many hours the player needs to rest in order to be fully healed
virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) = 0;
///< This is used by every service to determine the price of objects given the trading skills of the player and NPC.
@ -88,6 +92,36 @@ namespace MWBase
virtual int countDeaths (const std::string& id) const = 0;
///< Return the number of deaths for actors with the given ID.
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
enum OffenseType
{
OT_Theft, // Taking items owned by an NPC or a faction you are not a member of
OT_Assault, // Attacking a peaceful NPC
OT_Murder, // Murdering a peaceful NPC
OT_Trespassing, // Staying in a cell you are not allowed in (where is this defined?)
OT_SleepingInOwnedBed, // Sleeping in a bed owned by an NPC or a faction you are not a member of
OT_Pickpocket // Entering pickpocket mode, leaving it, and being detected. Any items stolen are a separate crime (Theft)
};
/**
* @brief Commit a crime. If any actors witness the crime and report it,
* reportCrime will be called automatically.
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
* @return was the crime reported?
*/
virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
/// @return was it illegal, and someone saw you doing it?
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
enum PersuasionType
{
PT_Admire,

View file

@ -137,8 +137,8 @@ namespace MWBase
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
/// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
virtual void setValue (const std::string& id, const std::string& value) = 0;
virtual void setValue (const std::string& id, int value) = 0;
@ -204,6 +204,7 @@ namespace MWBase
virtual void activateQuickKey (int index) = 0;
virtual std::string getSelectedSpell() = 0;
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
virtual void setSelectedEnchantItem(const MWWorld::Ptr& item) = 0;
virtual void setSelectedWeapon(const MWWorld::Ptr& item) = 0;
@ -226,17 +227,14 @@ namespace MWBase
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons = std::vector<std::string>(), bool showInDialogueModeOnly = false) = 0;
virtual void staticMessageBox(const std::string& message) = 0;
virtual void removeStaticMessageBox() = 0;
virtual void enterPressed () = 0;
virtual void activateKeyPressed () = 0;
virtual int readPressedButton() = 0;
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
virtual void onFrame (float frameDuration) = 0;
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues() = 0;
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues() = 0;
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
virtual SkillList getPlayerMinorSkills() = 0;
virtual SkillList getPlayerMajorSkills() = 0;

View file

@ -40,7 +40,6 @@ namespace ESM
namespace MWRender
{
class ExternalRendering;
class Animation;
}
@ -113,6 +112,7 @@ namespace MWBase
virtual const MWWorld::Fallback *getFallback () const = 0;
virtual MWWorld::Player& getPlayer() = 0;
virtual MWWorld::Ptr getPlayerPtr() = 0;
virtual const MWWorld::ESMStore& getStore() const = 0;
@ -130,7 +130,7 @@ namespace MWBase
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
///< get north vector (OGRE coordinates) for given interior cell
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
///< get a list of teleport door markers for a given cell, to be displayed on the local map
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
@ -157,6 +157,10 @@ namespace MWBase
///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells.
virtual MWWorld::Ptr searchPtr (const std::string& name, bool activeOnly) = 0;
///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells.
virtual MWWorld::Ptr getPtrViaHandle (const std::string& handle) = 0;
///< Return a pointer to a liveCellRef with the given Ogre handle.
@ -366,8 +370,6 @@ namespace MWBase
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
virtual int canRest() = 0;
///< check if the player is allowed to rest \n
/// 0 - yes \n
@ -414,12 +416,53 @@ namespace MWBase
virtual bool toggleGodMode() = 0;
/**
* @brief startSpellCast attempt to start casting a spell. Might fail immediately if conditions are not met.
* @param actor
* @return true if the spell can be casted (i.e. the animation should start)
*/
virtual bool startSpellCast (const MWWorld::Ptr& actor) = 0;
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
// Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const = 0;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// @note id must be lower case
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id) = 0;
enum DetectionType
{
Detect_Enchantment,
Detect_Key,
Detect_Creature
};
/// List all references (filtered by \a type) detected by \a ptr. The range
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
/// @note This also works for references in containers.
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
DetectionType type) = 0;
/// Update the value of some globals according to the world state, which may be used by dialogue entries.
/// This should be called when initiating a dialogue.
virtual void updateDialogueGlobals() = 0;
/// Moves all stolen items from \a ptr to the closest evidence chest.
virtual void confiscateStolenItems(const MWWorld::Ptr& ptr) = 0;
virtual void goToJail () = 0;
/// Spawn a random creature from a levelled list next to the player
virtual void spawnRandomCreature(const std::string& creatureList) = 0;
};
}

View file

@ -96,7 +96,11 @@ namespace MWClass
std::string text;
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
{
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
info.text = text;
return info;

View file

@ -128,6 +128,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
info.text = text;

View file

@ -17,7 +17,6 @@
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/player.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp"
@ -252,6 +251,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
@ -291,44 +291,36 @@ namespace MWClass
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
if (ptr.getCellRef().mCharge == 0)
return std::make_pair(0, "#{sInventoryMessage1}");
// slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
if (slots_.first.empty())
return std::make_pair(0, "");
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
if(race->mData.mFlags & ESM::Race::Beast)
{
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PRT_Head)
return std::make_pair(0, "#{sNotifyMessage13}");
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
return std::make_pair(0, "#{sNotifyMessage14}");
}
}
for (std::vector<int>::const_iterator slot=slots_.first.begin();
slot!=slots_.first.end(); ++slot)
{
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
if(race->mData.mFlags & ESM::Race::Beast)
{
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
{
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PRT_Head)
{
return std::make_pair(0, "#{sNotifyMessage13}");
}
}
}
if (*slot == MWWorld::InventoryStore::Slot_Boots)
{
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
{
return std::make_pair(0, "#{sNotifyMessage14}");
}
}
}
}
// If equipping a shield, check if there's a twohanded weapon conflicting with it
if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft)
{
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);

View file

@ -140,6 +140,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -14,7 +14,6 @@
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/player.hpp"
#include "../mwgui/tooltips.hpp"
@ -195,6 +194,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
@ -235,37 +235,26 @@ namespace MWClass
// slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
if (slots_.first.empty())
return std::make_pair(0, "");
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
for (std::vector<int>::const_iterator slot=slots_.first.begin();
slot!=slots_.first.end(); ++slot)
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
if(race->mData.mFlags & ESM::Race::Beast)
{
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
if(race->mData.mFlags & ESM::Race::Beast)
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
{
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PRT_Head)
return std::make_pair(0, "#{sNotifyMessage13}");
}
}
if (*slot == MWWorld::InventoryStore::Slot_Boots)
{
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
return std::make_pair(0, "#{sNotifyMessage15}");
}
}
if((*itr).mPart == ESM::PRT_Head)
return std::make_pair(0, "#{sNotifyMessage13}");
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
return std::make_pair(0, "#{sNotifyMessage15}");
}
}
return std::make_pair (1, "");
}

View file

@ -16,7 +16,6 @@
#include "../mwworld/actionopen.hpp"
#include "../mwworld/actiontrap.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwgui/tooltips.hpp"
@ -53,7 +52,7 @@ namespace MWClass
ptr.get<ESM::Container>();
data->mContainerStore.fill(
ref->mBase->mInventory, ptr.getCellRef().mOwner, MWBase::Environment::get().getWorld()->getStore());
ref->mBase->mInventory, ptr.getCellRef().mOwner, ptr.getCellRef().mFaction, MWBase::Environment::get().getWorld()->getStore());
// store
ptr.getRefData().setCustomData (data.release());
@ -108,7 +107,7 @@ namespace MWClass
const std::string lockedSound = "LockedChest";
const std::string trapActivationSound = "Disarm Trap Fail";
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player);
bool needKey = ptr.getCellRef().mLockLevel>0;
@ -216,6 +215,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -68,14 +68,14 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
// creature stats
data->mCreatureStats.getAttribute(0).set (ref->mBase->mData.mStrength);
data->mCreatureStats.getAttribute(1).set (ref->mBase->mData.mIntelligence);
data->mCreatureStats.getAttribute(2).set (ref->mBase->mData.mWillpower);
data->mCreatureStats.getAttribute(3).set (ref->mBase->mData.mAgility);
data->mCreatureStats.getAttribute(4).set (ref->mBase->mData.mSpeed);
data->mCreatureStats.getAttribute(5).set (ref->mBase->mData.mEndurance);
data->mCreatureStats.getAttribute(6).set (ref->mBase->mData.mPersonality);
data->mCreatureStats.getAttribute(7).set (ref->mBase->mData.mLuck);
data->mCreatureStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mData.mStrength);
data->mCreatureStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mData.mIntelligence);
data->mCreatureStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mData.mWillpower);
data->mCreatureStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mData.mAgility);
data->mCreatureStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mData.mSpeed);
data->mCreatureStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mData.mEndurance);
data->mCreatureStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mData.mPersonality);
data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck);
data->mCreatureStats.setHealth (ref->mBase->mData.mHealth);
data->mCreatureStats.setMagicka (ref->mBase->mData.mMana);
data->mCreatureStats.setFatigue (ref->mBase->mData.mFatigue);
@ -84,10 +84,10 @@ namespace MWClass
data->mCreatureStats.getAiSequence().fill(ref->mBase->mAiPackage);
data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello);
data->mCreatureStats.setAiSetting (1, ref->mBase->mAiData.mFight);
data->mCreatureStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
data->mCreatureStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
data->mCreatureStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
// spells
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
@ -95,10 +95,12 @@ namespace MWClass
data->mCreatureStats.getSpells().add (*iter);
// inventory
data->mContainerStore.fill(ref->mBase->mInventory, getId(ptr),
data->mContainerStore.fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore());
data->mContainerStore.add("gold_001", ref->mBase->mData.mGold, ptr);
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
// (except for gold you gave him)
data->mContainerStore.add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr);
// store
ptr.getRefData().setCustomData (data.release());
@ -413,6 +415,14 @@ namespace MWClass
return MWWorld::Ptr(&cell.mCreatures.insert(*ref), &cell);
}
bool Creature::isFlying(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Flies;
}
int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name)
{
if(name == "left")

View file

@ -99,6 +99,8 @@ namespace MWClass
isActor() const {
return true;
}
virtual bool isFlying (const MWWorld::Ptr &ptr) const;
};
}

View file

@ -8,7 +8,6 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/failedaction.hpp"
@ -97,7 +96,7 @@ namespace MWClass
if (needKey && hasKey)
{
if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer())
if(actor == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
ptr.getCellRef().mLockLevel = 0;
// using a key disarms the trap
@ -118,7 +117,7 @@ namespace MWClass
{
// teleport door
/// \todo remove this if clause once ActionTeleport can also support other actors
if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()==actor)
if (MWBase::Environment::get().getWorld()->getPlayerPtr()==actor)
{
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ref->mRef.mDestCell, ref->mRef.mDoorDest));

View file

@ -12,7 +12,6 @@
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/actioneat.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -149,10 +148,11 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player);
int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase();

View file

@ -187,6 +187,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -145,6 +145,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -93,7 +93,9 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();
int value = (ptr.getCellRef().mGoldValue == 1) ? ref->mBase->mData.mValue : ptr.getCellRef().mGoldValue;
int value = ref->mBase->mData.mValue;
if (ptr.getCellRef().mGoldValue > 1 && ptr.getRefData().getCount() == 1)
value = ptr.getCellRef().mGoldValue;
if (ptr.getCellRef().mSoul != "")
{
@ -184,6 +186,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
@ -242,7 +245,11 @@ namespace MWClass
item.get<ESM::Miscellaneous>();
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc)
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001");
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_005")
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_010")
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_025")
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_100");
}
float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const
@ -252,4 +259,11 @@ namespace MWClass
return ref->mBase->mData.mWeight;
}
bool Miscellaneous::isKey(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();
return ref->mBase->mData.mIsKey;
}
}

View file

@ -57,6 +57,8 @@ namespace MWClass
virtual float getWeight (const MWWorld::Ptr& ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
virtual bool isKey (const MWWorld::Ptr &ptr) const;
};
}

View file

@ -21,6 +21,7 @@
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/spellcasting.hpp"
#include "../mwmechanics/disease.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp"
@ -66,7 +67,7 @@ namespace
for (int i=0; i<ESM::Attribute::Length; ++i)
{
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
creatureStats.getAttribute(i).setBase (male ? attribute.mMale : attribute.mFemale);
creatureStats.setAttribute(i, male ? attribute.mMale : attribute.mFemale);
}
// class bonus
@ -78,7 +79,7 @@ namespace
int attribute = class_->mData.mAttribute[i];
if (attribute>=0 && attribute<8)
{
creatureStats.getAttribute(attribute).setBase (
creatureStats.setAttribute(attribute,
creatureStats.getAttribute(attribute).getBase() + 10);
}
}
@ -109,7 +110,7 @@ namespace
}
modifierSum += add;
}
creatureStats.getAttribute(attribute).setBase ( std::min(creatureStats.getAttribute(attribute).getBase()
creatureStats.setAttribute(attribute, std::min(creatureStats.getAttribute(attribute).getBase()
+ static_cast<int>((level-1) * modifierSum+0.5), 100) );
}
@ -179,29 +180,29 @@ namespace
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
{
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
{
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
break;
}
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
{
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
break;
}
}
for (int k = 0; k < 5; ++k)
{
// is this a minor or major skill?
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
{
majorMultiplier = 1.0f;
break;
}
// is this a minor or major skill?
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
{
majorMultiplier = 1.0f;
break;
}
}
// is this skill in the same Specialization as the class?
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillIndex);
if (skill->mData.mSpecialization == class_->mData.mSpecialization)
{
specMultiplier = 0.5f;
specBonus = 5;
specMultiplier = 0.5f;
specBonus = 5;
}
npcStats.getSkill(skillIndex).setBase(
@ -210,7 +211,7 @@ namespace
+ 5
+ raceBonus
+ specBonus
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100.0f));
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100));
}
}
}
@ -241,6 +242,9 @@ namespace MWClass
fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier");
fJumpRunMultiplier = gmst.find("fJumpRunMultiplier");
fWereWolfRunMult = gmst.find("fWereWolfRunMult");
fKnockDownMult = gmst.find("fKnockDownMult");
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
inited = true;
}
@ -274,14 +278,15 @@ namespace MWClass
for (unsigned int i=0; i< ESM::Skill::Length; ++i)
data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]);
data->mNpcStats.getAttribute(0).set (ref->mBase->mNpdt52.mStrength);
data->mNpcStats.getAttribute(1).set (ref->mBase->mNpdt52.mIntelligence);
data->mNpcStats.getAttribute(2).set (ref->mBase->mNpdt52.mWillpower);
data->mNpcStats.getAttribute(3).set (ref->mBase->mNpdt52.mAgility);
data->mNpcStats.getAttribute(4).set (ref->mBase->mNpdt52.mSpeed);
data->mNpcStats.getAttribute(5).set (ref->mBase->mNpdt52.mEndurance);
data->mNpcStats.getAttribute(6).set (ref->mBase->mNpdt52.mPersonality);
data->mNpcStats.getAttribute(7).set (ref->mBase->mNpdt52.mLuck);
data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt52.mStrength);
data->mNpcStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mNpdt52.mIntelligence);
data->mNpcStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mNpdt52.mWillpower);
data->mNpcStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mNpdt52.mAgility);
data->mNpcStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mNpdt52.mSpeed);
data->mNpcStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mNpdt52.mEndurance);
data->mNpcStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mNpdt52.mPersonality);
data->mNpcStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mNpdt52.mLuck);
data->mNpcStats.setHealth (ref->mBase->mNpdt52.mHealth);
data->mNpcStats.setMagicka (ref->mBase->mNpdt52.mMana);
data->mNpcStats.setFatigue (ref->mBase->mNpdt52.mFatigue);
@ -305,12 +310,23 @@ namespace MWClass
autoCalculateSkills(ref->mBase, data->mNpcStats);
}
if (data->mNpcStats.getFactionRanks().size())
{
static const int iAutoRepFacMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iAutoRepFacMod")->getInt();
static const int iAutoRepLevMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iAutoRepLevMod")->getInt();
int rank = data->mNpcStats.getFactionRanks().begin()->second;
data->mNpcStats.setReputation(iAutoRepFacMod * (rank+1) + iAutoRepLevMod * (data->mNpcStats.getLevel()-1));
}
data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage);
data->mNpcStats.setAiSetting (0, ref->mBase->mAiData.mHello);
data->mNpcStats.setAiSetting (1, ref->mBase->mAiData.mFight);
data->mNpcStats.setAiSetting (2, ref->mBase->mAiData.mFlee);
data->mNpcStats.setAiSetting (3, ref->mBase->mAiData.mAlarm);
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Hello, ref->mBase->mAiData.mHello);
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Fight, ref->mBase->mAiData.mFight);
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Flee, ref->mBase->mAiData.mFlee);
data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm);
// spells
for (std::vector<std::string>::const_iterator iter (ref->mBase->mSpells.mList.begin());
@ -318,13 +334,15 @@ namespace MWClass
data->mNpcStats.getSpells().add (*iter);
// inventory
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr),
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore());
// store
ptr.getRefData().setCustomData (data.release());
getContainerStore(ptr).add("gold_001", gold, ptr);
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
// (except for gold you gave him)
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, gold, ptr);
getInventoryStore(ptr).autoEquip(ptr);
}
@ -421,6 +439,20 @@ namespace MWClass
if(!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
weapon = MWWorld::Ptr();
// Reduce fatigue
// somewhat of a guess, but using the weapon weight makes sense
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
const float normalizedEncumbrance = getEncumbrance(ptr) / getCapacity(ptr);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty())
fatigueLoss += weapon.getClass().getWeight(weapon) * getNpcStats(ptr).getAttackStrength() * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
getCreatureStats(ptr).setFatigue(fatigue);
float dist = 100.0f * (!weapon.isEmpty() ?
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
gmst.find("fHandToHandReach")->getFloat());
@ -439,6 +471,10 @@ namespace MWClass
if(ptr.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->setEnemy(victim);
// Attacking peaceful NPCs is a crime
if (victim.getClass().isNpc() && victim.getClass().getCreatureStats(victim).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
MWBase::Environment::get().getMechanicsManager()->commitCrime(ptr, victim, MWBase::MechanicsManager::OT_Assault);
int weapskill = ESM::Skill::HandToHand;
if(!weapon.isEmpty())
weapskill = get(weapon).getEquipmentSkill(weapon);
@ -449,8 +485,8 @@ namespace MWClass
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
hitchance *= stats.getFatigueTerm();
hitchance += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyAttack)).mMagnitude -
mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
hitchance -= otherstats.getEvasion();
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
@ -482,16 +518,15 @@ namespace MWClass
weapon.getCellRef().mCharge = weapmaxhealth;
damage *= float(weapon.getCellRef().mCharge) / weapmaxhealth;
}
if(!othercls.hasDetected(victim, ptr))
{
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
if (!MWBase::Environment::get().getWorld()->getGodModeState())
weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
// Weapon broken? unequip it
if (weapon.getCellRef().mCharge == 0)
weapon = *inv.unequipItem(weapon, ptr);
}
healthdmg = true;
}
@ -504,14 +539,9 @@ namespace MWClass
float maxstrike = gmst.find("fMaxHandToHandMult")->getFloat();
damage = stats.getSkill(weapskill).getModified();
damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength());
if(!othercls.hasDetected(victim, ptr))
{
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f);
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f)
|| (otherstats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0);
if(stats.isWerewolf())
{
healthdmg = true;
@ -535,6 +565,16 @@ namespace MWClass
if(ptr.getRefData().getHandle() == "player")
skillUsageSucceeded(ptr, weapskill, 0);
bool detected = MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, victim);
if(!detected)
{
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
if (othercls.getCreatureStats(victim).getKnockedDown())
damage *= gmst.find("fCombatKODamageMult")->getFloat();
// Apply "On hit" enchanted weapons
std::string enchantmentName = !weapon.isEmpty() ? weapon.getClass().getEnchantment(weapon) : "";
if (!enchantmentName.empty())
@ -597,12 +637,35 @@ namespace MWClass
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
}
if (!attacker.isEmpty())
MWMechanics::diseaseContact(ptr, attacker);
if(damage > 0.0f)
{
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
// something, alert the character controller, scripts, etc.
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
if (roll < chance)
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
}
getCreatureStats(ptr).setAttacked(true);
// Check for knockdown
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
* iKnockDownOddsMult->getInt() * 0.01 + iKnockDownOddsBase->getInt();
roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
{
getCreatureStats(ptr).setKnockedDown(true);
}
else
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
if(object.isEmpty())
{
@ -643,6 +706,11 @@ namespace MWClass
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
armorref.mCharge);
// Armor broken? unequip it
if (armorref.mCharge == 0)
inv.unequipItem(armor, ptr);
switch(get(armor).getEquipmentSkill(armor))
{
case ESM::Skill::LightArmor:
@ -837,10 +905,11 @@ namespace MWClass
float moveSpeed;
if(normalizedEncumbrance >= 1.0f)
moveSpeed = 0.0f;
else if(mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude > 0)
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
world->isLevitationEnabled())
{
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude);
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
flySpeed = std::max(0.0f, flySpeed);
@ -851,7 +920,7 @@ namespace MWClass
float swimSpeed = walkSpeed;
if(Npc::getStance(ptr, Run, false))
swimSpeed = runSpeed;
swimSpeed *= 1.0f + 0.01f * mageffects.get(MWMechanics::EffectKey(1/*swift swim*/)).mMagnitude;
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
fSwimRunAthleticsMult->getFloat();
moveSpeed = swimSpeed;
@ -885,7 +954,7 @@ namespace MWClass
float x = fJumpAcrobaticsBase->getFloat() +
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
x += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude * 64;
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
x *= encumbranceTerm;
if(Npc::getStance(ptr, Run, false))
@ -908,7 +977,7 @@ namespace MWClass
{
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
@ -1000,7 +1069,8 @@ namespace MWClass
float Npc::getCapacity (const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
return stats.getAttribute(0).getModified()*5;
static const float fEncumbranceStrMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fEncumbranceStrMult")->getFloat();
return stats.getAttribute(0).getModified()*fEncumbranceStrMult;
}
float Npc::getEncumbrance (const MWWorld::Ptr& ptr) const
@ -1013,8 +1083,8 @@ namespace MWClass
if(!stats.isWerewolf())
{
weight = getContainerStore(ptr).getWeight();
weight -= stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).mMagnitude;
weight += stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).mMagnitude;
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude;
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude;
if(weight < 0.0f)
weight = 0.0f;
}
@ -1230,4 +1300,7 @@ namespace MWClass
const ESM::GameSetting *Npc::fJumpAcroMultiplier;
const ESM::GameSetting *Npc::fJumpRunMultiplier;
const ESM::GameSetting *Npc::fWereWolfRunMult;
const ESM::GameSetting *Npc::fKnockDownMult;
const ESM::GameSetting *Npc::iKnockDownOddsMult;
const ESM::GameSetting *Npc::iKnockDownOddsBase;
}

View file

@ -33,6 +33,9 @@ namespace MWClass
static const ESM::GameSetting *fJumpAcroMultiplier;
static const ESM::GameSetting *fJumpRunMultiplier;
static const ESM::GameSetting *fWereWolfRunMult;
static const ESM::GameSetting *fKnockDownMult;
static const ESM::GameSetting *iKnockDownOddsMult;
static const ESM::GameSetting *iKnockDownOddsBase;
public:

View file

@ -13,7 +13,6 @@
#include "../mwworld/cellstore.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp"
@ -133,7 +132,7 @@ namespace MWClass
info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->mBase->mEffects);
// hide effects the player doesnt know about
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player);
int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase();
int i=0;
@ -153,6 +152,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
@ -166,7 +166,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Potion> *ref =
ptr.get<ESM::Potion>();
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayerPtr();
// remove used potion (assume it is present in inventory)
ptr.getContainerStore()->remove(ptr, 1, actor);

View file

@ -144,6 +144,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -148,6 +148,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}

View file

@ -355,6 +355,7 @@ namespace MWClass
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->mRef.mOwner, "Owner");
text += MWGui::ToolTips::getMiscString(ref->mRef.mFaction, "Faction");
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
}
@ -388,28 +389,26 @@ namespace MWClass
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
{
if (ptr.getCellRef().mCharge == 0)
return std::make_pair(0, "#{sInventoryMessage1}");
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
// equip the item in the first free slot
for (std::vector<int>::const_iterator slot=slots_.first.begin();
slot!=slots_.first.end(); ++slot)
if (slots_.first.empty())
return std::make_pair (0, "");
if(ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
{
if(*slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
if(ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
{
return std::make_pair (2, "");
}
}
return std::make_pair(1, "");
return std::make_pair (2, "");
}
return std::make_pair (0, "");
return std::make_pair(1, "");
}
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const

View file

@ -30,7 +30,6 @@
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "../mwgui/dialogue.hpp"
@ -126,6 +125,8 @@ namespace MWDialogue
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
{
mLastTopic = "";
mPermanentDispositionChange = 0;
mTemporaryDispositionChange = 0;
mChoice = -1;
mIsInChoice = false;
@ -142,6 +143,7 @@ namespace MWDialogue
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
updateTopics();
updateGlobals();
//greeting
const MWWorld::Store<ESM::Dialogue> &dialogs =
@ -251,7 +253,7 @@ namespace MWDialogue
}
}
void DialogueManager::executeTopic (const std::string& topic, bool randomResponse)
void DialogueManager::executeTopic (const std::string& topic)
{
Filter filter (mActor, mChoice, mTalkedTo);
@ -262,12 +264,9 @@ namespace MWDialogue
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, true, true);
if (!infos.empty())
const ESM::DialInfo* info = filter.search(dialogue, true);
if (info)
{
const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0];
parseText (info->mResponse);
std::string title;
@ -300,6 +299,11 @@ namespace MWDialogue
}
}
void DialogueManager::updateGlobals()
{
MWBase::Environment::get().getWorld()->updateDialogueGlobals();
}
void DialogueManager::updateTopics()
{
std::list<std::string> keywordList;
@ -494,7 +498,7 @@ namespace MWDialogue
else if (curDisp + mTemporaryDispositionChange > 100)
mTemporaryDispositionChange = 100 - curDisp;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Speechcraft, success ? 0 : 1);
std::string text;
@ -509,7 +513,7 @@ namespace MWDialogue
text = "Bribe";
}
executeTopic (text + (success ? " Success" : " Fail"), true);
executeTopic (text + (success ? " Success" : " Fail"));
}
int DialogueManager::getTemporaryDispositionChange() const
@ -517,9 +521,19 @@ namespace MWDialogue
return mTemporaryDispositionChange;
}
void DialogueManager::applyTemporaryDispositionChange(int delta)
void DialogueManager::applyDispositionChange(int delta)
{
int oldTemp = mTemporaryDispositionChange;
mTemporaryDispositionChange += delta;
// don't allow increasing beyond 100 or decreasing below 0
int curDisp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
if (curDisp + mTemporaryDispositionChange < 0)
mTemporaryDispositionChange = -curDisp;
else if (curDisp + mTemporaryDispositionChange > 100)
mTemporaryDispositionChange = 100 - curDisp;
int diff = mTemporaryDispositionChange - oldTemp;
mPermanentDispositionChange += diff;
}
bool DialogueManager::checkServiceRefused()

View file

@ -40,11 +40,12 @@ namespace MWDialogue
void parseText (const std::string& text);
void updateTopics();
void updateGlobals();
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
void executeScript (const std::string& script);
void executeTopic (const std::string& topic, bool randomResponse=false);
void executeTopic (const std::string& topic);
public:
@ -76,7 +77,7 @@ namespace MWDialogue
virtual void persuade (int type);
virtual int getTemporaryDispositionChange () const;
virtual void applyTemporaryDispositionChange (int delta);
virtual void applyDispositionChange (int delta);
};

View file

@ -5,9 +5,9 @@
#include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/inventorystore.hpp"
@ -92,7 +92,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
{
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
// check player faction
if (!info.mPcFaction.empty())
@ -133,7 +133,8 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
if (isCreature)
return true;
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor)
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange();
// 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);
@ -210,7 +211,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
case SelectWrapper::Function_PcHealthPercent:
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() /
MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified();
@ -220,7 +221,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
case SelectWrapper::Function_PcDynamicStat:
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
float value = MWWorld::Class::get (player).getCreatureStats (player).
getDynamic (select.getArgument()).getCurrent();
@ -244,7 +245,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) const
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
switch (select.getFunction())
{
@ -277,7 +278,8 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
case SelectWrapper::Function_AiSetting:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument());
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (
(MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified();
case SelectWrapper::Function_PcAttribute:
@ -417,7 +419,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) const
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
switch (select.getFunction())
{
@ -505,14 +507,13 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
std::string faction =
MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first;
std::set<std::string>& expelled = MWWorld::Class::get (player).getNpcStats (player).getExpelled();
return expelled.find (faction)!=expelled.end();
return player.getClass().getNpcStats(player).getExpelled(faction);
}
case SelectWrapper::Function_PcVampire:
return MWWorld::Class::get (player).getNpcStats (player).isVampire();
return MWWorld::Class::get (player).getCreatureStats(player).getMagicEffects().
get(ESM::MagicEffect::Vampirism).mMagnitude > 0;
case SelectWrapper::Function_TalkedToPc:
@ -524,7 +525,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_Detected:
return MWWorld::Class::get (mActor).hasDetected (mActor, player);
return MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, mActor);
case SelectWrapper::Function_Attacked:

View file

@ -8,7 +8,6 @@
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "inventoryitemmodel.hpp"
@ -143,9 +142,9 @@ namespace MWGui
void AlchemyWindow::open()
{
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayerPtr());
InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayerPtr());
mSortModel = new SortFilterItemModel(model);
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
mItemView->setModel (mSortModel);
@ -154,7 +153,7 @@ namespace MWGui
int index = 0;
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayerPtr());
for (MWMechanics::Alchemy::TToolsIterator iter (mAlchemy.beginTools());
iter!=mAlchemy.endTools() && index<static_cast<int> (mApparatus.size()); ++iter, ++index)

View file

@ -8,7 +8,6 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/player.hpp"
#include "formatting.hpp"
@ -44,6 +43,11 @@ namespace MWGui
adjustButton(mNextPageButton);
adjustButton(mPrevPageButton);
mLeftPage->setNeedMouseFocus(true);
mLeftPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
mRightPage->setNeedMouseFocus(true);
mRightPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
if (mNextPageButton->getSize().width == 64)
{
// english button has a 7 pixel wide strip of garbage on its right edge
@ -54,6 +58,14 @@ namespace MWGui
center();
}
void BookWindow::onMouseWheel(MyGUI::Widget *_sender, int _rel)
{
if (_rel < 0)
nextPage();
else
prevPage();
}
void BookWindow::clearPages()
{
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
@ -89,6 +101,7 @@ namespace MWGui
parent = mRightPage;
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
pageWidget->setNeedMouseFocus(false);
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
mPages.push_back(pageWidget);
++i;
@ -124,7 +137,7 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->playSound("Item Book Up", 1.0, 1.0);
MWWorld::ActionTake take(mBook);
take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
take.execute (MWBase::Environment::get().getWorld()->getPlayerPtr());
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book);
}

View file

@ -25,6 +25,7 @@ namespace MWGui
void onPrevPageButtonClicked (MyGUI::Widget* sender);
void onCloseButtonClicked (MyGUI::Widget* sender);
void onTakeButtonClicked (MyGUI::Widget* sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void updatePages();
void clearPages();

View file

@ -13,7 +13,6 @@
#include "../mwmechanics/creaturestats.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/fallback.hpp"
#include "../mwworld/player.hpp"
namespace
{
@ -47,7 +46,7 @@ namespace
void updatePlayerHealth()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats(player);
creatureStats.updateHealth();
@ -75,7 +74,7 @@ namespace MWGui
mGenerateClassSpecializations[2] = 0;
}
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
{
if (mReviewDialog)
{
@ -113,7 +112,7 @@ namespace MWGui
}
}
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
{
if (mReviewDialog)
mReviewDialog->setSkillValue(parSkill, value);
@ -220,8 +219,8 @@ namespace MWGui
mReviewDialog->setBirthSign(mPlayerBirthSignId);
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats stats = MWWorld::Class::get(player).getCreatureStats(player);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
mReviewDialog->setHealth ( stats.getHealth() );
mReviewDialog->setMagicka( stats.getMagicka() );
@ -229,8 +228,8 @@ namespace MWGui
}
{
std::map<int, MWMechanics::Stat<int> > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
for (std::map<int, MWMechanics::Stat<int> >::iterator it = attributes.begin();
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
it != attributes.end(); ++it)
{
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
@ -238,8 +237,8 @@ namespace MWGui
}
{
std::map<int, MWMechanics::Stat<float> > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
for (std::map<int, MWMechanics::Stat<float> >::iterator it = skills.begin();
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
it != skills.end(); ++it)
{
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);

View file

@ -31,9 +31,9 @@ namespace MWGui
//Show a dialog
void spawnDialog(const char id);
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
void configureSkills (const SkillList& major, const SkillList& minor);
void doRenderUpdate();

View file

@ -29,11 +29,12 @@ namespace MWGui
MyGUI::Button* backButton;
getWidget(backButton, "BackButton");
backButton->setCaptionWithReplacing("#{sMessageQuestionAnswer3}");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
MyGUI::Button* okButton;
getWidget(okButton, "OKButton");
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
okButton->setCaptionWithReplacing("#{sMessageQuestionAnswer2}");
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onOkClicked);
}
@ -466,7 +467,7 @@ namespace MWGui
std::string CreateClassDialog::getName() const
{
return mEditName->getOnlyText();
return mEditName->getCaption();
}
std::string CreateClassDialog::getDescription() const

View file

@ -228,8 +228,8 @@ namespace MWGui
DescriptionDialog();
~DescriptionDialog();
std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; }
void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); }
std::string getTextInput() const { return mTextEdit->getCaption(); }
void setTextInput(const std::string &text) { mTextEdit->setCaption(text); }
protected:
void onOkClicked(MyGUI::Widget* _sender);

View file

@ -119,8 +119,6 @@ namespace MWGui
// Set up the log window
mHistory->setOverflowToTheLeft(true);
mHistory->setEditStatic(true);
mHistory->setVisibleVScroll(true);
// compiler
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
@ -215,7 +213,7 @@ namespace MWGui
{
std::vector<std::string> matches;
listNames();
mCommandLine->setCaption(complete( mCommandLine->getCaption(), matches ));
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
#if 0
int i = 0;
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
@ -234,7 +232,7 @@ namespace MWGui
{
// If the user was editing a string, store it for later
if(mCurrent == mCommandHistory.end())
mEditString = mCommandLine->getCaption();
mEditString = mCommandLine->getOnlyText();
if(mCurrent != mCommandHistory.begin())
{
@ -259,7 +257,7 @@ namespace MWGui
void Console::acceptCommand(MyGUI::EditBox* _sender)
{
const std::string &cm = mCommandLine->getCaption();
const std::string &cm = mCommandLine->getOnlyText();
if(cm.empty()) return;
// Add the command to the history, and set the current pointer to
@ -406,13 +404,14 @@ namespace MWGui
setTitle("#{sConsoleTitle} (" + object.getCellRef().mRefID + ")");
mPtr = object;
}
// User clicked on an object. Restore focus to the console command line.
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
}
else
{
setTitle("#{sConsoleTitle}");
mPtr = MWWorld::Ptr();
}
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
}
void Console::onReferenceUnavailable()

View file

@ -6,9 +6,13 @@
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/pickpocket.hpp"
#include "countdialog.hpp"
#include "tradewindow.hpp"
@ -61,8 +65,9 @@ namespace MWGui
mDraggedWidget = baseWidget;
MyGUI::ImageBox* image = baseWidget->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
int pos = path.rfind(".");
path.erase(pos);
size_t pos = path.rfind(".");
if (pos != std::string::npos)
path.erase(pos);
path.append(".dds");
image->setImageTexture(path);
image->setNeedMouseFocus(false);
@ -122,6 +127,7 @@ namespace MWGui
, mSelectedItem(-1)
, mModel(NULL)
, mSortModel(NULL)
, mPickpocketDetected(false)
{
getWidget(mDisposeCorpseButton, "DisposeCorpseButton");
getWidget(mTakeButton, "TakeButton");
@ -133,6 +139,7 @@ namespace MWGui
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ContainerWindow::onKeyPressed);
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
setCoord(200,0,600,300);
@ -170,6 +177,9 @@ namespace MWGui
void ContainerWindow::dragItem(MyGUI::Widget* sender, int count)
{
if (!onTakeItem(mModel->getItem(mSelectedItem), count))
return;
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mModel, mItemView, count);
}
@ -207,12 +217,13 @@ namespace MWGui
void ContainerWindow::open(const MWWorld::Ptr& container, bool loot)
{
mPickpocketDetected = false;
mPtr = container;
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && !loot)
{
// we are stealing stuff
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
mModel = new PickpocketItemModel(player, new InventoryItemModel(container));
}
else
@ -224,11 +235,46 @@ namespace MWGui
mItemView->setModel (mSortModel);
MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
// or we end up using a possibly invalid model.
setTitle(MWWorld::Class::get(container).getName(container));
}
void ContainerWindow::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
{
if (_key == MyGUI::KeyCode::Space)
onCloseButtonClicked(mCloseButton);
if (_key == MyGUI::KeyCode::Return || _key == MyGUI::KeyCode::NumpadEnter)
onTakeAllButtonClicked(mTakeButton);
}
void ContainerWindow::close()
{
WindowBase::close();
if (dynamic_cast<PickpocketItemModel*>(mModel)
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
&& !MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)
// If it was already detected while taking an item, no need to check now
&& !mPickpocketDetected
)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::Pickpocket pickpocket(player, mPtr);
if (pickpocket.finish())
{
MWBase::Environment::get().getMechanicsManager()->reportCrime(
player, mPtr, MWBase::MechanicsManager::OT_Pickpocket);
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
mPickpocketDetected = true;
return;
}
}
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
@ -254,8 +300,13 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
playerModel->copyItem(mModel->getItem(i), mModel->getItem(i).mCount);
mModel->removeItem(mModel->getItem(i), mModel->getItem(i).mCount);
const ItemStack& item = mModel->getItem(i);
if (!onTakeItem(item, item.mCount))
break;
playerModel->copyItem(item, item.mCount);
mModel->removeItem(item, item.mCount);
}
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
@ -282,4 +333,30 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (dynamic_cast<PickpocketItemModel*>(mModel))
{
MWMechanics::Pickpocket pickpocket(player, mPtr);
if (pickpocket.pick(item.mBase, count))
{
int value = item.mBase.getClass().getValue(item.mBase) * count;
MWBase::Environment::get().getMechanicsManager()->reportCrime(
player, MWWorld::Ptr(), MWBase::MechanicsManager::OT_Theft, value);
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
mPickpocketDetected = true;
return false;
}
else
player.getClass().skillUsageSucceeded(player, ESM::Skill::Sneak, 1);
}
else
{
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
}
return true;
}
}

View file

@ -52,10 +52,13 @@ namespace MWGui
ContainerWindow(DragAndDrop* dragAndDrop);
void open(const MWWorld::Ptr& container, bool loot=false);
virtual void close();
private:
DragAndDrop* mDragAndDrop;
bool mPickpocketDetected;
MWGui::ItemView* mItemView;
SortFilterItemModel* mSortModel;
ItemModel* mModel;
@ -72,6 +75,10 @@ namespace MWGui
void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
void onKeyPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char);
/// @return is taking the item allowed?
bool onTakeItem(const ItemStack& item, int count);
virtual void onReferenceUnavailable();
};

View file

@ -76,10 +76,7 @@ void ContainerItemModel::copyItem (const ItemStack& item, size_t count)
const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1];
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
throw std::runtime_error("Item to copy needs to be from a different container!");
int origCount = item.mBase.getRefData().getCount();
item.mBase.getRefData().setCount(count);
source.getClass().getContainerStore(source).add(item.mBase, source);
item.mBase.getRefData().setCount(origCount);
source.getClass().getContainerStore(source).add(item.mBase, count, source);
}
void ContainerItemModel::removeItem (const ItemStack& item, size_t count)

View file

@ -12,7 +12,6 @@
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwdialogue/dialoguemanagerimp.hpp"
@ -21,7 +20,6 @@
#include "list.hpp"
#include "tradewindow.hpp"
#include "spellbuyingwindow.hpp"
#include "inventorywindow.hpp"
#include "travelwindow.hpp"
#include "bookpage.hpp"
@ -69,24 +67,24 @@ namespace MWGui
void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWBase::MechanicsManager::PersuasionType type;
if (sender == mAdmireButton) type = MWBase::MechanicsManager::PT_Admire;
else if (sender == mIntimidateButton) type = MWBase::MechanicsManager::PT_Intimidate;
else if (sender == mTauntButton) type = MWBase::MechanicsManager::PT_Taunt;
else if (sender == mBribe10Button)
{
player.getClass().getContainerStore(player).remove("gold_001", 10, player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, 10, player);
type = MWBase::MechanicsManager::PT_Bribe10;
}
else if (sender == mBribe100Button)
{
player.getClass().getContainerStore(player).remove("gold_001", 100, player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, 100, player);
type = MWBase::MechanicsManager::PT_Bribe100;
}
else /*if (sender == mBribe1000Button)*/
{
player.getClass().getContainerStore(player).remove("gold_001", 1000, player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, 1000, player);
type = MWBase::MechanicsManager::PT_Bribe1000;
}
@ -100,7 +98,8 @@ namespace MWGui
WindowModal::open();
center();
int playerGold = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mBribe10Button->setEnabled (playerGold >= 10);
mBribe100Button->setEnabled (playerGold >= 100);

View file

@ -5,13 +5,11 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "itemselection.hpp"
#include "container.hpp"
#include "inventorywindow.hpp"
#include "sortfilteritemmodel.hpp"
@ -106,7 +104,7 @@ namespace MWGui
void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
mEnchanting.setSelfEnchanting(true);
mEnchanting.setEnchanter(player);
@ -149,7 +147,7 @@ namespace MWGui
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected);
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel);
mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyEnchantable);
}
@ -236,7 +234,7 @@ namespace MWGui
mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected);
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel);
mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyChargedSoulstones);
//MWBase::Environment::get().getWindowManager()->messageBox("#{sInventorySelectNoSoul}");
@ -259,7 +257,7 @@ namespace MWGui
{
if (mEffects.size() <= 0)
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage30}");
MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu11}");
return;
}
@ -290,7 +288,9 @@ namespace MWGui
mEnchanting.setNewItemName(mName->getCaption());
mEnchanting.setEffect(mEffectList);
if (mEnchanting.getEnchantPrice() > MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
if (mEnchanting.getEnchantPrice() > playerGold)
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}");
return;

View file

@ -6,7 +6,6 @@
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
@ -55,6 +54,8 @@ namespace MWGui
, mWorldMouseOver(false)
, mEnemyHealthTimer(0)
, mIsDrowning(false)
, mWeaponSpellTimer(0.f)
, mDrowningFlashTheta(0.f)
{
setCoord(0,0, width, height);
@ -240,7 +241,7 @@ namespace MWGui
if (world->canPlaceObject(mouseX, mouseY))
world->placeObject(object, mouseX, mouseY, mDragAndDrop->mDraggedCount);
else
world->dropObjectOnGround(world->getPlayer().getPlayer(), object, mDragAndDrop->mDraggedCount);
world->dropObjectOnGround(world->getPlayerPtr(), object, mDragAndDrop->mDraggedCount);
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
@ -318,7 +319,7 @@ namespace MWGui
void HUD::onWeaponClicked(MyGUI::Widget* _sender)
{
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf())
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
@ -330,7 +331,7 @@ namespace MWGui
void HUD::onMagicClicked(MyGUI::Widget* _sender)
{
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf())
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
@ -515,7 +516,7 @@ namespace MWGui
mWeapStatus->setProgressPosition(0);
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayer().getPlayer();
MWWorld::Ptr player = world->getPlayerPtr();
if (MWWorld::Class::get(player).getNpcStats(player).isWerewolf())
mWeapImage->setImageTexture("icons\\k\\tx_werewolf_hand.dds");
else

View file

@ -42,10 +42,7 @@ void InventoryItemModel::copyItem (const ItemStack& item, size_t count)
{
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
throw std::runtime_error("Item to copy needs to be from a different container!");
int origCount = item.mBase.getRefData().getCount();
item.mBase.getRefData().setCount(count);
mActor.getClass().getContainerStore(mActor).add(item.mBase, mActor);
item.mBase.getRefData().setCount(origCount);
mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor);
}
@ -72,7 +69,7 @@ void InventoryItemModel::update()
// NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken.
// Vanilla likely uses a hack like this since there's no other way to prevent it from
// being shown or taken.
if(item.getCellRef().mRefID == "WerewolfRobe")
if(item.getCellRef().mRefID == "werewolfrobe")
continue;
ItemStack newItem (item, this, item.getRefData().getCount());

View file

@ -8,11 +8,13 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/action.hpp"
#include "../mwscript/interpretercontext.hpp"
#include "../mwbase/scriptmanager.hpp"
#include "bookwindow.hpp"
#include "scrollwindow.hpp"
@ -33,7 +35,7 @@ namespace MWGui
, mTrading(false)
, mLastXSize(0)
, mLastYSize(0)
, mPreview(MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ())
, mPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())
, mPreviewDirty(true)
, mDragAndDrop(dragAndDrop)
, mSelectedItem(-1)
@ -84,7 +86,7 @@ namespace MWGui
void InventoryWindow::updatePlayer()
{
mPtr = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel(mSortModel);
@ -120,10 +122,13 @@ namespace MWGui
Settings::Manager::getFloat(setting + " y", "Windows") * viewSize.height);
MyGUI::IntSize size (Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width,
Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height);
if (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight())
mPreviewDirty = true;
mMainWidget->setPosition(pos);
mMainWidget->setSize(size);
adjustPanes();
mPreviewDirty = true;
}
TradeItemModel* InventoryWindow::getTradeModel()
@ -160,6 +165,14 @@ namespace MWGui
MWWorld::Ptr object = item.mBase;
int count = item.mCount;
// Bound items may not be moved
if (item.mBase.getCellRef().mRefID.size() > 6
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}");
return;
}
if (item.mType == ItemStack::Type_Equipped)
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
@ -265,7 +278,7 @@ namespace MWGui
void InventoryWindow::open()
{
mPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
mPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
updateEncumbranceBar();
@ -340,6 +353,48 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->setWeaponVisibility(!mPinned);
}
void InventoryWindow::useItem(const MWWorld::Ptr &ptr)
{
const std::string& script = ptr.getClass().getScript(ptr);
// If the item has a script, set its OnPcEquip to 1
if (!script.empty()
// Another morrowind oddity: when an item has skipped equipping and pcskipequip is reset to 0 afterwards,
// the next time it is equipped will work normally, but will not set onpcequip
&& (ptr != mSkippedToEquip || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 1))
ptr.getRefData().getLocals().setVarByInt(script, "onpcequip", 1);
// Give the script a chance to run once before we do anything else
// this is important when setting pcskipequip as a reaction to onpcequip being set (bk_treasuryreport does this)
if (!script.empty())
{
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
}
if (script.empty() || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 0)
{
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(ptr).use(ptr);
action->execute (MWBase::Environment::get().getWorld()->getPlayerPtr());
// this is necessary for books/scrolls: if they are already in the player's inventory,
// the "Take" button should not be visible.
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
// without screwing up future book windows
MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false);
MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false);
mSkippedToEquip = MWWorld::Ptr();
}
else
mSkippedToEquip = ptr;
mItemView->update();
notifyContentChanged();
}
void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender)
{
if (mDragAndDrop->mIsOnDragAndDrop)
@ -353,29 +408,12 @@ namespace MWGui
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
MWWorld::ContainerStoreIterator it = invStore.begin();
int origCount = ptr.getRefData().getCount();
ptr.getRefData().setCount(mDragAndDrop->mDraggedCount);
it = invStore.add(ptr, mPtr);
ptr.getRefData().setCount(origCount);
it = invStore.add(ptr, mDragAndDrop->mDraggedCount, mPtr);
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
ptr = *it;
}
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(ptr).use(ptr);
action->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
// this is necessary for books/scrolls: if they are already in the player's inventory,
// the "Take" button should not be visible.
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
// without screwing up future book windows
MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false);
MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false);
mItemView->update();
notifyContentChanged();
useItem(ptr);
}
else
{
@ -414,7 +452,7 @@ namespace MWGui
// NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla
// likely uses a hack like this since there's no other way to prevent it from being
// taken.
if(item.getCellRef().mRefID == "WerewolfRobe")
if(item.getCellRef().mRefID == "werewolfrobe")
return MWWorld::Ptr();
return item;
}
@ -424,7 +462,7 @@ namespace MWGui
void InventoryWindow::updateEncumbranceBar()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
float capacity = MWWorld::Class::get(player).getCapacity(player);
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
@ -439,19 +477,6 @@ namespace MWGui
updateEncumbranceBar();
}
int InventoryWindow::getPlayerGold()
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (MWWorld::ContainerStoreIterator it = invStore.begin();
it != invStore.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
return it->getRefData().getCount();
}
return 0;
}
void InventoryWindow::setTrading(bool trading)
{
mTrading = trading;
@ -504,13 +529,11 @@ namespace MWGui
return;
int count = object.getRefData().getCount();
if (object.getCellRef().mGoldValue > 1)
count = object.getCellRef().mGoldValue;
// add to player inventory
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr newObject = *MWWorld::Class::get (player).getContainerStore (player).add (object, player);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player);
// remove from world
MWBase::Environment::get().getWorld()->deleteObject (object);
@ -525,6 +548,8 @@ namespace MWGui
if (i == mTradeModel->getItemCount())
throw std::runtime_error("Added item not found");
mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count);
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
}
MyGUI::IntCoord InventoryWindow::getAvatarScreenCoord ()

View file

@ -31,8 +31,6 @@ namespace MWGui
void pickUpObject (MWWorld::Ptr object);
int getPlayerGold();
MyGUI::IntCoord getAvatarScreenCoord();
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
@ -48,6 +46,8 @@ namespace MWGui
void updatePlayer();
void useItem(const MWWorld::Ptr& ptr);
void setGuiMode(GuiMode mode);
private:
@ -76,6 +76,8 @@ namespace MWGui
MyGUI::Button* mFilterMagic;
MyGUI::Button* mFilterMisc;
MWWorld::Ptr mSkippedToEquip;
GuiMode mGuiMode;
int mLastXSize;

View file

@ -6,7 +6,6 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/fallback.hpp"
@ -59,7 +58,7 @@ namespace MWGui
void LevelupDialog::setAttributeValues()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
@ -115,7 +114,7 @@ namespace MWGui
void LevelupDialog::open()
{
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayer().getPlayer();
MWWorld::Ptr player = world->getPlayerPtr();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
@ -155,7 +154,7 @@ namespace MWGui
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
@ -166,11 +165,12 @@ namespace MWGui
// increase attributes
for (int i=0; i<3; ++i)
{
MWMechanics::Stat<int>& attribute = creatureStats.getAttribute(mSpentAttributes[i]);
MWMechanics::AttributeValue attribute = creatureStats.getAttribute(mSpentAttributes[i]);
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
if (attribute.getBase() >= 100)
attribute.setBase(100);
creatureStats.setAttribute(mSpentAttributes[i], attribute);
}
creatureStats.levelUp();

View file

@ -103,27 +103,80 @@ namespace MWGui
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
{
// Workaround to not make the marker visible if it's under fog of war
applyFogOfWar ();
}
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
{
// Workaround to not make the marker visible if it's under fog of war
applyFogOfWar ();
}
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
{
MyGUI::IntPoint widgetPos;
// normalized cell coordinates
float nX,nY;
markerPos.interior = mInterior;
if (!mInterior)
{
int cellX, cellY;
MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
const int cellSize = 8192;
nX = (worldX - cellSize * cellX) / cellSize;
// Image space is -Y up, cells are Y up
nY = 1 - (worldY - cellSize * cellY) / cellSize;
float cellDx = cellX - mCurX;
float cellDy = cellY - mCurY;
markerPos.cellX = cellX;
markerPos.cellY = cellY;
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellDx) * 512,
nY * 512 - (cellDy-1) * 512);
}
else
{
int cellX, cellY;
Ogre::Vector2 worldPos (worldX, worldY);
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
markerPos.cellX = cellX;
markerPos.cellY = cellY;
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512,
nY * 512 + (1+cellY-mCurY) * 512);
}
markerPos.nX = nX;
markerPos.nY = nY;
return widgetPos;
}
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
return; // don't do anything if we're still in the same cell
mCurX = x;
mCurY = y;
mInterior = interior;
mChanged = false;
// clear all previous markers
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
{
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door")
{
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
}
}
// Update the map textures
for (int mx=0; mx<3; ++mx)
{
for (int my=0; my<3; ++my)
@ -138,78 +191,57 @@ namespace MWGui
box->setImageTexture(image);
else
box->setImageTexture("black.png");
// door markers
// interior map only consists of one cell, so handle the markers only once
if (interior && (mx != 2 || my != 2))
continue;
MWWorld::CellStore* cell;
if (interior)
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
else
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
{
MWBase::World::DoorMarker marker = *it;
// convert world coordinates to normalized cell coordinates
MyGUI::IntCoord widgetCoord;
float nX,nY;
int cellDx, cellDy;
if (!interior)
{
const int cellSize = 8192;
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8);
}
else
{
Ogre::Vector2 position (marker.x, marker.y);
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8);
}
static int counter = 0;
++counter;
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
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);
MarkerPosition markerPos;
markerPos.interior = interior;
markerPos.cellX = interior ? cellDx : x + mx - 1;
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
markerPos.nX = nX;
markerPos.nY = nY;
markerWidget->setUserData(markerPos);
}
}
}
mInterior = interior;
mCurX = x;
mCurY = y;
mChanged = false;
// fog of war
MWBase::World* world = MWBase::Environment::get().getWorld();
// Retrieve the door markers we want to show
std::vector<MWBase::World::DoorMarker> doors;
if (interior)
{
MWWorld::CellStore* cell = world->getInterior (mPrefix);
world->getDoorMarkers(cell, doors);
}
else
{
for (int dX=-1; dX<2; ++dX)
{
for (int dY=-1; dY<2; ++dY)
{
MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
world->getDoorMarkers(cell, doors);
}
}
}
// Create a widget for each marker
int counter = 0;
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
{
MWBase::World::DoorMarker marker = *it;
MarkerPosition markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
8, 8);
++counter;
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", marker.name);
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
}
updateMarkers();
applyFogOfWar();
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
@ -222,6 +254,8 @@ namespace MWGui
void LocalMapBase::setPlayerPos(const float x, const float y)
{
updateMarkers();
if (x == mLastPositionX && y == mLastPositionY)
return;
@ -255,6 +289,88 @@ namespace MWGui
mLastDirectionY = y;
}
void LocalMapBase::addDetectionMarkers(int type)
{
std::vector<MWWorld::Ptr> markers;
MWBase::World* world = MWBase::Environment::get().getWorld();
world->listDetectedReferences(
world->getPlayerPtr(),
markers, MWBase::World::DetectionType(type));
if (markers.empty())
return;
std::string markerTexture;
MyGUI::Colour markerColour;
if (type == MWBase::World::Detect_Creature)
{
markerTexture = "textures\\menu_map_dcreature.dds";
markerColour = MyGUI::Colour(1,0,0,1);
}
if (type == MWBase::World::Detect_Key)
{
markerTexture = "textures\\menu_map_dkey.dds";
markerColour = MyGUI::Colour(0,1,0,1);
}
if (type == MWBase::World::Detect_Enchantment)
{
markerTexture = "textures\\menu_map_dmagic.dds";
markerColour = MyGUI::Colour(0,0,1,1);
}
int counter = 0;
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
{
const ESM::Position& worldPos = it->getRefData().getPosition();
MarkerPosition markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
8, 8);
++counter;
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
markerWidget->setImageTexture(markerTexture);
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
markerWidget->setColour(markerColour);
}
}
void LocalMapBase::updateMarkers()
{
// clear all previous markers
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
{
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
{
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
}
}
addDetectionMarkers(MWBase::World::Detect_Creature);
addDetectionMarkers(MWBase::World::Detect_Key);
addDetectionMarkers(MWBase::World::Detect_Enchantment);
// Add marker for the spot marked with Mark magic effect
MWWorld::CellStore* markedCell = NULL;
ESM::Position markedPosition;
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
if (markedCell && markedCell->isExterior() == !mInterior
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->mCell->mName, mPrefix)))
{
MarkerPosition markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
8, 8);
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default, "MarkerMarked");
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
}
}
// ------------------------------------------------------------------------------------------
MapWindow::MapWindow(const std::string& cacheDir)
@ -319,7 +435,7 @@ namespace MWGui
static int _counter=0;
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
@ -385,7 +501,7 @@ namespace MWGui
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
{
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
}
@ -396,20 +512,18 @@ namespace MWGui
void MapWindow::globalMapUpdatePlayer ()
{
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
float worldX, worldY;
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
worldX *= mGlobalMapRender->getWidth();
worldY *= mGlobalMapRender->getHeight();
// for interiors, we have no choice other than using the last position & direction.
/// \todo save this last position in the savegame?
// For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
{
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayerPtr().getRefData ().getBaseNode ()->_getDerivedPosition ();
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayerPtr().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
float worldX, worldY;
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
worldX *= mGlobalMapRender->getWidth();
worldY *= mGlobalMapRender->getHeight();
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
@ -444,4 +558,19 @@ namespace MWGui
"#{sWorld}");
}
void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY)
{
float x, y;
mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y);
x *= mGlobalMapRender->getWidth();
y *= mGlobalMapRender->getHeight();
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(x - 16, y - 16));
// set the view offset so that player is in the center
MyGUI::IntSize viewsize = mGlobalMap->getSize();
MyGUI::IntPoint viewoffs(0.5*viewsize.width - x, 0.5*viewsize.height - y);
mGlobalMap->setViewOffset(viewoffs);
}
}

View file

@ -55,9 +55,16 @@ namespace MWGui
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
virtual void notifyPlayerUpdate() {}
virtual void notifyMapChanged() {}
// Update markers (Detect X effects, Mark/Recall effects)
// Note, door markers handled in setActiveCell
void updateMarkers();
void addDetectionMarkers(int type);
OEngine::GUI::Layout* mLayout;
bool mMapDragAndDrop;
@ -81,6 +88,8 @@ namespace MWGui
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
void cellExplored(int x, int y);
void setGlobalMapPlayerPosition (float worldX, float worldY);
virtual void open();
private:

View file

@ -8,12 +8,9 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "inventorywindow.hpp"
namespace MWGui
{
@ -36,7 +33,9 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
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));
@ -69,8 +68,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
MyGUI::Button* button =
mList->createWidget<MyGUI::Button>(
(price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
mList->createWidget<MyGUI::Button>("SandTextButton",
0,
currentY,
0,
@ -80,7 +78,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
currentY += 18;
button->setEnabled(price<=MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold());
button->setEnabled(price<=playerGold);
button->setUserString("Price", boost::lexical_cast<std::string>(price));
button->setUserData(*iter);
button->setCaptionWithReplacing(name);
@ -93,7 +91,7 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
mGoldLabel->setCaptionWithReplacing("#{sGold}: "
+ boost::lexical_cast<std::string>(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()));
+ boost::lexical_cast<std::string>(playerGold));
}
void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
@ -119,8 +117,8 @@ void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender)
int price = boost::lexical_cast<int>(sender->getUserString("Price"));
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
player.getClass().getContainerStore(player).remove("gold_001", price, player);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
startRepair(mActor);
}

View file

@ -8,12 +8,21 @@
namespace MWGui
{
MessageBoxManager::MessageBoxManager ()
MessageBoxManager::MessageBoxManager (float timePerChar)
{
mMessageBoxSpeed = 0.1;
mInterMessageBoxe = NULL;
mStaticMessageBox = NULL;
mLastButtonPressed = -1;
mMessageBoxSpeed = timePerChar;
}
MessageBoxManager::~MessageBoxManager ()
{
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
for (; it != mMessageBoxes.end(); ++it)
{
delete *it;
}
}
void MessageBoxManager::onFrame (float frameDuration)
@ -53,7 +62,8 @@ namespace MWGui
{
MessageBox *box = new MessageBox(*this, message);
box->mCurrentTime = 0;
box->mMaxTime = message.length()*mMessageBoxSpeed;
std::string realMessage = MyGUI::LanguageManager::getInstance().replaceTags(message);
box->mMaxTime = realMessage.length()*mMessageBoxSpeed;
if(stat)
mStaticMessageBox = box;
@ -117,12 +127,6 @@ namespace MWGui
mMessageBoxSpeed = speed;
}
void MessageBoxManager::okayPressed ()
{
if(mInterMessageBoxe != NULL)
mInterMessageBoxe->okayPressed();
}
int MessageBoxManager::readPressedButton ()
{
int pressed = mLastButtonPressed;
@ -323,23 +327,25 @@ namespace MWGui
}
}
}
void InteractiveMessageBox::okayPressed()
{
// Set key focus to "Ok" button
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok)
{
buttonActivated(*button);
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
MyGUI::InputManager::getInstance().setKeyFocusWidget(*button);
(*button)->eventKeyButtonPressed += MyGUI::newDelegate(this, &InteractiveMessageBox::onKeyPressed);
break;
}
}
}
void InteractiveMessageBox::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
{
if (_key == MyGUI::KeyCode::Return || _key == MyGUI::KeyCode::NumpadEnter || _key == MyGUI::KeyCode::Space)
buttonActivated(_sender);
}
void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)

View file

@ -22,7 +22,8 @@ namespace MWGui
class MessageBoxManager
{
public:
MessageBoxManager ();
MessageBoxManager (float timePerChar);
~MessageBoxManager ();
void onFrame (float frameDuration);
void createMessageBox (const std::string& message, bool stat = false);
void removeStaticMessageBox ();
@ -32,7 +33,6 @@ namespace MWGui
bool removeMessageBox (MessageBox *msgbox);
void setMessageBoxSpeed (int speed);
void okayPressed();
int readPressedButton ();
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
@ -73,7 +73,6 @@ namespace MWGui
{
public:
InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons);
void okayPressed ();
void mousePressed (MyGUI::Widget* _widget);
int readPressedButton ();
@ -81,6 +80,7 @@ namespace MWGui
private:
void buttonActivated (MyGUI::Widget* _widget);
void onKeyPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char);
MessageBoxManager& mMessageBoxManager;
MyGUI::EditBox* mMessageWidget;

View file

@ -40,6 +40,14 @@ namespace MWGui
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
{
const ItemStack& item = mSourceModel->getItem(i);
// Bound items may not be stolen
if (item.mBase.getCellRef().mRefID.size() > 6
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
{
continue;
}
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
&& item.mType != ItemStack::Type_Equipped)
mItems.push_back(item);

View file

@ -2,7 +2,6 @@
#include <boost/lexical_cast.hpp>
#include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwmechanics/spellcasting.hpp"
@ -126,7 +125,7 @@ namespace MWGui
mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &QuickKeysMenu::onAssignItemCancel);
}
mItemSelectionDialog->setVisible(true);
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
mAssignDialog->setVisible (false);
}
@ -267,15 +266,41 @@ namespace MWGui
QuickKeyType type = *button->getUserData<QuickKeyType>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
if (type == Type_Item || type == Type_MagicItem)
{
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
// make sure the item is available
if (item.getRefData ().getCount() < 1)
{
// Try searching for a compatible replacement
std::string id = item.getCellRef().mRefID;
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id))
{
item = *it;
button->getChildAt(0)->setUserData(item);
break;
}
}
if (item.getRefData().getCount() < 1)
{
// No replacement was found
MWBase::Environment::get().getWindowManager ()->messageBox (
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
return;
}
}
}
if (type == Type_Magic)
{
std::string spellId = button->getChildAt(0)->getUserString("Spell");
spells.setSelectedSpell(spellId);
store.setSelectedEnchantItem(store.end());
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
}
@ -283,41 +308,12 @@ namespace MWGui
{
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
// make sure the item is available
if (item.getRefData ().getCount() < 1)
{
// TODO: Try to find a replacement with the same ID?
MWBase::Environment::get().getWindowManager ()->messageBox (
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
return;
}
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(item).use(item);
action->execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
// this is necessary for books/scrolls: if they are already in the player's inventory,
// the "Take" button should not be visible.
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
// without screwing up future book windows
MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false);
MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false);
// since we changed equipping status, update the inventory window
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
}
else if (type == Type_MagicItem)
{
MWWorld::Ptr item = *button->getChildAt (0)->getUserData<MWWorld::Ptr>();
// make sure the item is available
if (item.getRefData ().getCount() == 0)
{
MWBase::Environment::get().getWindowManager ()->messageBox (
"#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item));
return;
}
// retrieve ContainerStoreIterator to the item
MWWorld::ContainerStoreIterator it = store.begin();
for (; it != store.end(); ++it)
@ -335,14 +331,10 @@ namespace MWGui
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
MWWorld::ActionEquip action(item);
action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ());
// since we changed equipping status, update the inventory window
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
action.execute (MWBase::Environment::get().getWorld ()->getPlayerPtr());
}
store.setSelectedEnchantItem(it);
spells.setSelectedSpell("");
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
}
}
@ -425,7 +417,7 @@ namespace MWGui
const int spellHeight = 18;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();

View file

@ -7,7 +7,6 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
@ -85,7 +84,7 @@ void Recharge::updateView()
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
for (MWWorld::ContainerStoreIterator iter (store.begin());
iter!=store.end(); ++iter)
@ -141,7 +140,7 @@ void Recharge::onItemClicked(MyGUI::Widget *sender)
MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player);

View file

@ -3,8 +3,6 @@
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/player.hpp"
namespace MWGui
{
ReferenceInterface::ReferenceInterface()
@ -18,7 +16,7 @@ namespace MWGui
void ReferenceInterface::checkReferenceAvailable()
{
MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayerPtr().getCell();
// check if player has changed cell, or count of the reference has become 0
if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL)

View file

@ -6,7 +6,6 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
@ -88,7 +87,7 @@ void Repair::updateRepairView()
int currentY = 0;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
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));

View file

@ -65,7 +65,7 @@ namespace MWGui
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue());
}
// Setup skills
@ -74,7 +74,7 @@ namespace MWGui
for (int i = 0; i < ESM::Skill::Length; ++i)
{
mSkillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
mSkillValues.insert(std::make_pair(i, MWMechanics::SkillValue()));
mSkillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
}
@ -152,7 +152,7 @@ namespace MWGui
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
}
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
{
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
if (attr == mAttributeWidgets.end())
@ -161,7 +161,7 @@ namespace MWGui
attr->second->setAttributeValue(value);
}
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value)
{
mSkillValues[skillId] = value;
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
@ -279,9 +279,9 @@ namespace MWGui
continue;
assert(skillId >= 0 && skillId < ESM::Skill::Length);
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
float base = stat.getBase();
float modified = stat.getModified();
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
int base = stat.getBase();
int modified = stat.getModified();
std::string state = "normal";
if (modified > base)

View file

@ -38,10 +38,10 @@ namespace MWGui
void setMagicka(const MWMechanics::DynamicStat<float>& value);
void setFatigue(const MWMechanics::DynamicStat<float>& value);
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value);
void configureSkills(const SkillList& major, const SkillList& minor);
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value);
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value);
virtual void open();
@ -85,7 +85,7 @@ namespace MWGui
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
std::map<int, MWMechanics::Stat<float> > mSkillValues;
std::map<int, MWMechanics::SkillValue > mSkillValues;
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
std::string mName, mRaceId, mBirthSignId;
ESM::Class mKlass;

View file

@ -6,7 +6,6 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/player.hpp"
#include "formatting.hpp"
@ -90,7 +89,7 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->playSound("Item Book Up", 1.0, 1.0);
MWWorld::ActionTake take(mScroll);
take.execute (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
take.execute (MWBase::Environment::get().getWorld()->getPlayerPtr());
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Scroll);
}

View file

@ -92,6 +92,7 @@ namespace MWGui
{
getWidget(mOkButton, "OkButton");
getWidget(mBestAttackButton, "BestAttackButton");
getWidget(mGrabCursorButton, "GrabCursorButton");
getWidget(mSubtitlesButton, "SubtitlesButton");
getWidget(mCrosshairButton, "CrosshairButton");
getWidget(mResolutionList, "ResolutionList");
@ -133,6 +134,7 @@ namespace MWGui
mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mBestAttackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mGrabCursorButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled);
@ -201,6 +203,7 @@ namespace MWGui
mSubtitlesButton->setCaptionWithReplacing(Settings::Manager::getBool("subtitles", "GUI") ? "#{sOn}" : "#{sOff}");
mCrosshairButton->setCaptionWithReplacing(Settings::Manager::getBool("crosshair", "HUD") ? "#{sOn}" : "#{sOff}");
mBestAttackButton->setCaptionWithReplacing(Settings::Manager::getBool("best attack", "Game") ? "#{sOn}" : "#{sOff}");
mGrabCursorButton->setCaptionWithReplacing(Settings::Manager::getBool("grab cursor", "Input") ? "#{sOn}" : "#{sOff}");
float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin);
mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1));
@ -393,7 +396,8 @@ namespace MWGui
Settings::Manager::setBool("subtitles", "GUI", newState);
else if (_sender == mBestAttackButton)
Settings::Manager::setBool("best attack", "Game", newState);
else if (_sender == mGrabCursorButton)
Settings::Manager::setBool("grab cursor", "Input", newState);
apply();
}
}

View file

@ -33,6 +33,7 @@ namespace MWGui
MyGUI::Button* mSubtitlesButton;
MyGUI::Button* mCrosshairButton;
MyGUI::Button* mBestAttackButton;
MyGUI::Button* mGrabCursorButton;
// graphics
MyGUI::ListBox* mResolutionList;

View file

@ -8,14 +8,11 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "inventorywindow.hpp"
namespace MWGui
{
const int SpellBuyingWindow::sLineHeight = 18;
@ -43,15 +40,19 @@ namespace MWGui
int price = spell->mData.mCost*store.get<ESM::GameSetting>().find("fSpellValueMult")->getFloat();
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
MyGUI::Button* toAdd =
mSpellsView->createWidget<MyGUI::Button>(
(price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton",
"SandTextButton",
0,
mCurrentY,
200,
sLineHeight,
MyGUI::Align::Default
);
toAdd->setEnabled(price<=playerGold);
mCurrentY += sLineHeight;
@ -103,7 +104,7 @@ namespace MWGui
bool SpellBuyingWindow::playerHasSpell(const std::string &id)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells();
for (MWMechanics::Spells::TIterator it = playerSpells.begin(); it != playerSpells.end(); ++it)
{
@ -117,17 +118,14 @@ namespace MWGui
{
int price = *_sender->getUserData<int>();
if (MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()>=price)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
spells.add (mSpellsWidgetMap.find(_sender)->second);
player.getClass().getContainerStore(player).remove("gold_001", price, player);
startSpellBuying(mPtr);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
spells.add (mSpellsWidgetMap.find(_sender)->second);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
startSpellBuying(mPtr);
MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
}
MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
}
void SpellBuyingWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
@ -137,7 +135,10 @@ namespace MWGui
void SpellBuyingWindow::updateLabels()
{
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()));
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold));
mPlayerGold->setCoord(8,
mPlayerGold->getTop(),
mPlayerGold->getTextSize().width,

View file

@ -7,14 +7,12 @@
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/spellcasting.hpp"
#include "tooltips.hpp"
#include "class.hpp"
#include "inventorywindow.hpp"
namespace
{
@ -334,7 +332,10 @@ namespace MWGui
return;
}
if (boost::lexical_cast<int>(mPriceLabel->getCaption()) > MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold())
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
if (boost::lexical_cast<int>(mPriceLabel->getCaption()) > playerGold)
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}");
return;
@ -342,9 +343,7 @@ namespace MWGui
mSpell.mName = mNameEdit->getCaption();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
player.getClass().getContainerStore(player).remove("gold_001", boost::lexical_cast<int>(mPriceLabel->getCaption()), player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, boost::lexical_cast<int>(mPriceLabel->getCaption()), player);
MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0);
@ -414,7 +413,7 @@ namespace MWGui
mPriceLabel->setCaption(boost::lexical_cast<std::string>(int(price)));
float chance = MWMechanics::getSpellSuccessChance(&mSpell, MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
float chance = MWMechanics::getSpellSuccessChance(&mSpell, MWBase::Environment::get().getWorld()->getPlayerPtr());
mSuccessChance->setCaption(boost::lexical_cast<std::string>(int(chance)));
}
@ -441,7 +440,7 @@ namespace MWGui
{
// get the list of magic effects that are known to the player
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();

View file

@ -9,7 +9,6 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp"
@ -22,7 +21,8 @@ namespace MWGui
{
void EffectSourceVisitor::visit (MWMechanics::EffectKey key,
const std::string& sourceName, float magnitude, float remainingTime)
const std::string& sourceName, const std::string& casterHandle,
float magnitude, float remainingTime)
{
MagicEffectInfo newEffectSource;
newEffectSource.mKey = key;
@ -39,7 +39,7 @@ namespace MWGui
{
// TODO: Tracking add/remove/expire would be better than force updating every frame
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);

View file

@ -43,7 +43,8 @@ namespace MWGui
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
virtual void visit (MWMechanics::EffectKey key,
const std::string& sourceName, float magnitude, float remainingTime = -1);
const std::string& sourceName, const std::string& casterHandle,
float magnitude, float remainingTime = -1);
};
class SpellIcons

View file

@ -5,7 +5,6 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/actionequip.hpp"
@ -81,66 +80,13 @@ namespace MWGui
// retrieve all player spells, divide them into Powers and Spells and sort them
std::vector<std::string> spellList;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
// the following code switches between selected enchanted item and selected spell (only one of these
// can be active at a time)
std::string selectedSpell = spells.getSelectedSpell();
MWWorld::Ptr selectedItem;
if (store.getSelectedEnchantItem() != store.end())
{
selectedSpell = "";
selectedItem = *store.getSelectedEnchantItem();
bool allowSelectedItem = true;
// make sure that the item is still in the player inventory, otherwise it can't be selected
bool found = false;
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
{
if (*it == selectedItem)
found = true;
}
if (!found)
allowSelectedItem = false;
// if the selected item can be equipped, make sure that it actually is equipped
std::pair<std::vector<int>, bool> slots_;
slots_ = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem);
if (!slots_.first.empty())
{
bool equipped = false;
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
{
if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem)
{
equipped = true;
break;
}
}
if (!equipped)
allowSelectedItem = false;
}
if (!allowSelectedItem)
{
store.setSelectedEnchantItem(store.end());
spells.setSelectedSpell("");
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
selectedItem = MWWorld::Ptr();
}
}
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
{
spellList.push_back (it->first);
}
const MWWorld::ESMStore &esmStore =
MWBase::Environment::get().getWorld()->getStore();
@ -210,7 +156,7 @@ namespace MWGui
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
if (*it == selectedSpell)
if (*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell())
t->setStateSelected(true);
mHeight += spellHeight;
@ -229,7 +175,7 @@ namespace MWGui
t->setUserString("Spell", *it);
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
t->setStateSelected(*it == selectedSpell);
t->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell());
// cost / success chance
MyGUI::Button* costChance = mSpellView->createWidget<MyGUI::Button>("SpellText",
@ -239,7 +185,7 @@ namespace MWGui
costChance->setCaption(cost + "/" + chance);
costChance->setTextAlign(MyGUI::Align::Right);
costChance->setNeedMouseFocus(false);
costChance->setStateSelected(*it == selectedSpell);
costChance->setStateSelected(*it == MWBase::Environment::get().getWindowManager()->getSelectedSpell());
mHeight += spellHeight;
@ -276,7 +222,9 @@ namespace MWGui
t->setUserString("Equipped", equipped ? "true" : "false");
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected);
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->setStateSelected(item == selectedItem);
if (store.getSelectedEnchantItem() != store.end())
t->setStateSelected(item == *store.getSelectedEnchantItem());
// cost / charge
MyGUI::Button* costCharge = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
@ -302,7 +250,8 @@ namespace MWGui
costCharge->setCaption(cost + "/" + charge);
costCharge->setTextAlign(MyGUI::Align::Right);
costCharge->setNeedMouseFocus(false);
costCharge->setStateSelected(item == selectedItem);
if (store.getSelectedEnchantItem() != store.end())
costCharge->setStateSelected(item == *store.getSelectedEnchantItem());
mHeight += spellHeight;
}
@ -348,10 +297,8 @@ namespace MWGui
void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::Spells& spells = stats.getSpells();
MWWorld::Ptr item = *_sender->getUserData<MWWorld::Ptr>();
// retrieve ContainerStoreIterator to the item
@ -372,14 +319,13 @@ namespace MWGui
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
MWWorld::ActionEquip action(item);
action.execute (MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ());
action.execute (MWBase::Environment::get().getWorld ()->getPlayerPtr());
// since we changed equipping status, update the inventory window
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
}
store.setSelectedEnchantItem(it);
spells.setSelectedSpell("");
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
updateSpells();
@ -388,10 +334,8 @@ namespace MWGui
void SpellWindow::onSpellSelected(MyGUI::Widget* _sender)
{
std::string spellId = _sender->getUserString("Spell");
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::Spells& spells = stats.getSpells();
if (MyGUI::InputManager::getInstance().isShiftPressed())
{
@ -419,7 +363,6 @@ namespace MWGui
}
else
{
spells.setSelectedSpell(spellId);
store.setSelectedEnchantItem(store.end());
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
}
@ -445,15 +388,12 @@ namespace MWGui
void SpellWindow::onDeleteSpellAccept()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
if (spells.getSelectedSpell() == mSpellToDelete)
{
spells.setSelectedSpell("");
if (MWBase::Environment::get().getWindowManager()->getSelectedSpell() == mSpellToDelete)
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
}
spells.remove(mSpellToDelete);

View file

@ -6,8 +6,8 @@
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -61,7 +61,7 @@ namespace MWGui
for (int i = 0; i < ESM::Skill::Length; ++i)
{
mSkillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
mSkillValues.insert(std::pair<int, MWMechanics::SkillValue >(i, MWMechanics::SkillValue()));
mSkillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, (MyGUI::TextBox*)NULL));
}
@ -102,7 +102,7 @@ namespace MWGui
adjustWindowCaption();
}
void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
void StatsWindow::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
{
static const char *ids[] =
{
@ -179,13 +179,13 @@ namespace MWGui
}
}
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
{
mSkillValues[parSkill] = value;
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
if (widget)
{
float modified = value.getModified(), base = value.getBase();
int modified = value.getModified(), base = value.getBase();
std::string text = boost::lexical_cast<std::string>(std::floor(modified));
std::string state = "normal";
if (modified > base)
@ -224,7 +224,7 @@ namespace MWGui
if (!mMainWidget->getVisible())
return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const MWMechanics::NpcStats &PCstats = MWWorld::Class::get(player).getNpcStats(player);
// level progress
@ -358,22 +358,20 @@ namespace MWGui
continue;
assert(skillId >= 0 && skillId < ESM::Skill::Length);
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
float base = stat.getBase();
float modified = stat.getModified();
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
int base = stat.getBase();
int modified = stat.getModified();
int progressPercent = stat.getProgress() * 100;
const MWWorld::ESMStore &esmStore =
MWBase::Environment::get().getWorld()->getStore();
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
assert(skill);
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
const ESM::Attribute* attr =
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
assert(attr);
std::string state = "normal";
if (modified > base)
@ -426,7 +424,7 @@ namespace MWGui
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::ESMStore &store = world->getStore();
const ESM::NPC *player =
world->getPlayer().getPlayer().get<ESM::NPC>()->mBase;
world->getPlayerPtr().get<ESM::NPC>()->mBase;
// race tooltip
const ESM::Race* playerRace = store.get<ESM::Race>().find(player->mRace);
@ -454,7 +452,7 @@ namespace MWGui
if (!mSkillWidgets.empty())
addSeparator(coord1, coord2);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const MWMechanics::NpcStats &PCstats = MWWorld::Class::get(player).getNpcStats(player);
const std::set<std::string> &expelled = PCstats.getExpelled();
@ -484,7 +482,6 @@ namespace MWGui
ESM::RankData rankData = faction->mData.mRankData[it->second+1];
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
assert(attr1 && attr2);
text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute1)
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);

View file

@ -26,11 +26,11 @@ namespace MWGui
void setPlayerName(const std::string& playerName);
/// Set value for the given ID.
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue (const std::string& id, const std::string& value);
void setValue (const std::string& id, int value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
void configureSkills (const SkillList& major, const SkillList& minor);
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
@ -61,7 +61,7 @@ namespace MWGui
MyGUI::ScrollView* mSkillView;
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
std::map<int, MWMechanics::Stat<float> > mSkillValues;
std::map<int, MWMechanics::SkillValue > mSkillValues;
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
FactionList mFactions; ///< Stores a list of factions and the current rank

View file

@ -15,8 +15,8 @@ namespace MWGui
public:
TextInputDialog();
std::string getTextInput() const { return mTextEdit ? mTextEdit->getOnlyText() : ""; }
void setTextInput(const std::string &text) { if (mTextEdit) mTextEdit->setOnlyText(text); }
std::string getTextInput() const { return mTextEdit->getCaption(); }
void setTextInput(const std::string &text) { mTextEdit->setCaption(text); }
void setNextButtonShow(bool shown);
void setTextLabel(const std::string &label);

View file

@ -149,11 +149,18 @@ namespace MWGui
if(!mMerchant.isEmpty())
{
MWWorld::Ptr base = item.mBase;
if(Misc::StringUtils::ciEqual(base.getCellRef().mRefID, "gold_001"))
if(Misc::StringUtils::ciEqual(base.getCellRef().mRefID, MWWorld::ContainerStore::sGoldId))
continue;
if(!MWWorld::Class::get(base).canSell(base, services))
continue;
// Bound items may not be bought
if (item.mBase.getCellRef().mRefID.size() > 6
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
{
continue;
}
// don't show equipped items
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
{

View file

@ -16,14 +16,13 @@
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/player.hpp"
#include "inventorywindow.hpp"
#include "itemview.hpp"
#include "sortfilteritemmodel.hpp"
#include "containeritemmodel.hpp"
#include "tradeitemmodel.hpp"
#include "countdialog.hpp"
#include "dialogue.hpp"
namespace MWGui
{
@ -211,11 +210,11 @@ namespace MWGui
if (amount > 0)
{
store.add("gold_001", amount, actor);
store.add(MWWorld::ContainerStore::sGoldId, amount, actor);
}
else
{
store.remove("gold_001", - amount, actor);
store.remove(MWWorld::ContainerStore::sGoldId, - amount, actor);
}
}
@ -252,8 +251,11 @@ namespace MWGui
return;
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
// check if the player can afford this
if (mCurrentBalance < 0 && MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold() < std::abs(mCurrentBalance))
if (mCurrentBalance < 0 && playerGold < std::abs(mCurrentBalance))
{
// user notification
MWBase::Environment::get().getWindowManager()->
@ -270,8 +272,6 @@ namespace MWGui
return;
}
MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(mCurrentBalance > mCurrentMerchantOffer)
{
//if npc is a creature: reject (no haggle)
@ -293,13 +293,13 @@ namespace MWGui
float clampedDisposition = std::max<int>(0,std::min<int>(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100));
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
const MWMechanics::NpcStats &sellerStats = mPtr.getClass().getNpcStats(mPtr);
const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player);
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
@ -318,16 +318,18 @@ namespace MWGui
messageBox("#{sNotifyMessage9}");
int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt();
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterFailDisposition);
if (mPtr.getClass().isNpc())
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterFailDisposition);
return;
}
//skill use!
MWWorld::Class::get(playerPtr).skillUsageSucceeded(playerPtr, ESM::Skill::Mercantile, 0);
player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0);
}
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition);
if (mPtr.getClass().isNpc())
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterSuccessDisposition);
// make the item transfer
mTradeModel->transferItems();
@ -336,10 +338,13 @@ namespace MWGui
// transfer the gold
if (mCurrentBalance != 0)
{
addOrRemoveGold(mCurrentBalance, playerPtr);
addOrRemoveGold(mCurrentBalance, player);
addOrRemoveGold(-mCurrentBalance, mPtr);
}
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());
std::string sound = "Item Gold Up";
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
@ -394,7 +399,10 @@ namespace MWGui
void TradeWindow::updateLabels()
{
mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()));
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast<std::string>(playerGold));
if (mCurrentBalance > 0)
{
@ -443,7 +451,7 @@ namespace MWGui
MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, MWWorld::ContainerStore::sGoldId))
merchantGold += it->getRefData().getCount();
}
return merchantGold;

View file

@ -28,8 +28,6 @@ namespace MWGui
void startTrade(const MWWorld::Ptr& actor);
void addOrRemoveGold(int gold, const MWWorld::Ptr& actor);
void onFrame(float frameDuration);
void borrowItem (int index, size_t count);
@ -95,6 +93,8 @@ namespace MWGui
void onIncreaseButtonTriggered();
void onDecreaseButtonTriggered();
void addOrRemoveGold(int gold, const MWWorld::Ptr& actor);
void updateLabels();
virtual void onReferenceUnavailable();

View file

@ -9,13 +9,11 @@
#include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "inventorywindow.hpp"
#include "tooltips.hpp"
namespace MWGui
@ -41,7 +39,10 @@ namespace MWGui
{
mPtr = actor;
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()));
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold));
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats (actor);
@ -72,7 +73,6 @@ namespace MWGui
MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator ();
MyGUI::Gui::getInstance ().destroyWidgets (widgets);
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
const MWWorld::Store<ESM::GameSetting> &gmst =
@ -83,11 +83,10 @@ namespace MWGui
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer
(mPtr,pcStats.getSkill (bestSkills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true);
std::string skin = (price > MWBase::Environment::get().getWindowManager()->getInventoryWindow ()->getPlayerGold ()) ? "SandTextGreyedOut" : "SandTextButton";
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(skin,
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>("SandTextButton",
MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default);
button->setEnabled(price <= playerGold);
button->setUserData(bestSkills[i].first);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
@ -115,7 +114,7 @@ namespace MWGui
{
int skillId = *sender->getUserData<int>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer ();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
const MWWorld::ESMStore &store =
@ -124,9 +123,6 @@ namespace MWGui
int price = pcStats.getSkill (skillId).getBase() * store.get<ESM::GameSetting>().find("iTrainingMod")->getInt ();
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
if (MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()<price)
return;
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mPtr).getNpcStats (mPtr);
if (npcStats.getSkill (skillId).getBase () <= pcStats.getSkill (skillId).getBase ())
{
@ -134,6 +130,14 @@ namespace MWGui
return;
}
// You can not train a skill above its governing attribute
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillId);
if (pcStats.getSkill(skillId).getBase() >= pcStats.getAttribute(skill->mData.mAttribute).getBase())
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage17}");
return;
}
// increase skill
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
@ -142,7 +146,7 @@ namespace MWGui
pcStats.increaseSkill (skillId, *class_, true);
// remove gold
player.getClass().getContainerStore(player).remove("gold_001", price, player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
// go back to game mode
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training);
@ -150,6 +154,8 @@ namespace MWGui
// advance time
MWBase::Environment::get().getWorld ()->advanceTime (2);
MWBase::Environment::get().getMechanicsManager()->rest(false);
MWBase::Environment::get().getMechanicsManager()->rest(false);
MWBase::Environment::get().getWorld ()->getFader()->fadeOut(0.25);
mFadeTimeRemaining = 0.5;

View file

@ -2,6 +2,8 @@
#include <boost/lexical_cast.hpp>
#include <OgreVector3.h>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp"
@ -9,12 +11,9 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "inventorywindow.hpp"
namespace MWGui
{
const int TravelWindow::sLineHeight = 18;
@ -51,13 +50,15 @@ namespace MWGui
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
if(interior)
{
price = gmst.find("fMagesGuildTravel")->getFloat();
}
else
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::Position PlayerPos = player.getRefData().getPosition();
float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) );
price = d/gmst.find("fTravelMult")->getFloat();
@ -65,7 +66,8 @@ namespace MWGui
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>((price>MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default);
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>("SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default);
toAdd->setEnabled(price<=playerGold);
mCurrentY += sLineHeight;
if(interior)
toAdd->setUserString("interior","y");
@ -121,13 +123,14 @@ namespace MWGui
int price;
iss >> price;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
if (MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()<price)
if (playerGold<price)
return;
player.getClass().getContainerStore(player).remove("gold_001", price, player);
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1);
ESM::Position pos = *_sender->getUserData<ESM::Position>();
@ -145,7 +148,7 @@ namespace MWGui
int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat());
for(int i = 0;i < hours;i++)
{
MWBase::Environment::get().getMechanicsManager ()->restoreDynamicStats ();
MWBase::Environment::get().getMechanicsManager ()->rest (true);
}
MWBase::Environment::get().getWorld()->advanceTime(hours);
@ -166,7 +169,10 @@ namespace MWGui
void TravelWindow::updateLabels()
{
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getPlayerGold()));
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold));
mPlayerGold->setCoord(8,
mPlayerGold->getTop(),
mPlayerGold->getTextSize().width,

View file

@ -9,7 +9,6 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
@ -49,6 +48,7 @@ namespace MWGui
, mRemainingTime(0.05)
, mCurHour(0)
, mManualHours(1)
, mInterruptAt(-1)
{
getWidget(mDateTimeText, "DateTimeText");
getWidget(mRestText, "RestText");
@ -145,43 +145,7 @@ namespace MWGui
void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender)
{
// we need to sleep for a specific time, and since that isn't calculated yet, we'll do it here
// I'm making the assumption here that the # of hours rested is calculated when rest is started
// TODO: the rougher logic here (calculating the hourly deltas) should really go into helper funcs elsewhere
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats stats = MWWorld::Class::get(player).getCreatureStats(player);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
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();
// this massive duplication is why it has to be put into helper functions instead
float fFatigueReturnBase = store.get<ESM::GameSetting>().find("fFatigueReturnBase")->getFloat();
float fFatigueReturnMult = store.get<ESM::GameSetting>().find("fFatigueReturnMult")->getFloat();
float fEndFatigueMult = store.get<ESM::GameSetting>().find("fEndFatigueMult")->getFloat();
float capacity = MWWorld::Class::get(player).getCapacity(player);
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
float hourlyFatigueDelta = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
hourlyFatigueDelta *= 3600 * fEndFatigueMult * stats.getAttribute(ESM::Attribute::Endurance).getModified();
float healthHours = hourlyHealthDelta >= 0.0
? (stats.getHealth().getBase() - stats.getHealth().getCurrent()) / hourlyHealthDelta
: 1.0f;
float magickaHours = stunted ? 0.0 :
hourlyMagickaDelta >= 0.0
? (stats.getMagicka().getBase() - stats.getMagicka().getCurrent()) / hourlyMagickaDelta
: 1.0f;
float fatigueHours = hourlyFatigueDelta >= 0.0
? (stats.getFatigue().getBase() - stats.getFatigue().getCurrent()) / hourlyFatigueDelta
: 1.0f;
int autoHours = int(std::ceil( std::max(std::max(healthHours, magickaHours), std::max(fatigueHours, 1.0f)) )); // this should use a variadic max if possible
int autoHours = MWBase::Environment::get().getMechanicsManager()->getHoursToRest();
startWaiting(autoHours);
}
@ -193,7 +157,8 @@ namespace MWGui
void WaitDialog::startWaiting(int hoursToWait)
{
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2);
MWBase::World* world = MWBase::Environment::get().getWorld();
world->getFader ()->fadeOut(0.2);
setVisible(false);
mProgressBar.setVisible (true);
@ -201,6 +166,30 @@ namespace MWGui
mCurHour = 0;
mHours = hoursToWait;
// FIXME: move this somewhere else?
mInterruptAt = -1;
MWWorld::Ptr player = world->getPlayerPtr();
if (mSleeping && player.getCell()->isExterior())
{
std::string regionstr = player.getCell()->mCell->mRegion;
if (!regionstr.empty())
{
const ESM::Region *region = world->getStore().get<ESM::Region>().find (regionstr);
if (!region->mSleepList.empty())
{
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->getFloat();
int x = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * hoursToWait; // [0, hoursRested]
float y = fSleepRandMod * hoursToWait;
if (x > y)
{
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->getFloat();
mInterruptAt = int(fSleepRestMod * hoursToWait);
mInterruptCreatureList = region->mSleepList;
}
}
}
}
mRemainingTime = 0.05;
mProgressBar.setProgress (0, mHours);
}
@ -218,7 +207,7 @@ namespace MWGui
void WaitDialog::setCanRest (bool canRest)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
bool full = (stats.getFatigue().getCurrent() >= stats.getFatigue().getModified())
&& (stats.getHealth().getCurrent() >= stats.getHealth().getModified())
@ -243,6 +232,13 @@ namespace MWGui
if (!mWaiting)
return;
if (mCurHour == mInterruptAt)
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sSleepInterrupt}");
MWBase::Environment::get().getWorld()->spawnRandomCreature(mInterruptCreatureList);
stopWaiting();
}
mRemainingTime -= dt;
while (mRemainingTime < 0)
@ -254,8 +250,7 @@ namespace MWGui
if (mCurHour <= mHours)
{
MWBase::Environment::get().getWorld ()->advanceTime (1);
if (mSleeping)
MWBase::Environment::get().getMechanicsManager ()->restoreDynamicStats ();
MWBase::Environment::get().getMechanicsManager ()->rest (mSleeping);
}
}
@ -272,7 +267,7 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed);
mWaiting = false;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const MWMechanics::NpcStats &pcstats = MWWorld::Class::get(player).getNpcStats(player);
// trigger levelup if possible

View file

@ -51,6 +51,9 @@ namespace MWGui
int mManualHours; // stores the hours to rest selected via slider
float mRemainingTime;
int mInterruptAt;
std::string mInterruptCreatureList;
WaitDialogProgressBar mProgressBar;
void onUntilHealedButtonClicked(MyGUI::Widget* sender);

View file

@ -178,7 +178,7 @@ namespace MWGui
}
if (mAttributeValueWidget)
{
AttributeValue::Type modified = mValue.getModified(), base = mValue.getBase();
int modified = mValue.getModified(), base = mValue.getBase();
static_cast<MyGUI::TextBox*>(mAttributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
if (modified > base)
mAttributeValueWidget->_setWidgetState("increased");
@ -528,14 +528,9 @@ namespace MWGui
if (mBarTextWidget)
{
if (mValue >= 0 && mMax > 0)
{
std::stringstream out;
out << mValue << "/" << mMax;
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
}
else
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
std::stringstream out;
out << mValue << "/" << mMax;
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
}
}
void MWDynamicStat::setTitle(const std::string& text)

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