1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-03 21:49:41 +00:00

Merge branch 'master' into illusion

This commit is contained in:
Capostrophic 2018-04-09 23:33:11 +03:00 committed by GitHub
commit d9acd19dc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
117 changed files with 1131 additions and 830 deletions

View file

@ -41,6 +41,7 @@ Programmers
Cory F. Cohen (cfcohen) Cory F. Cohen (cfcohen)
Cris Mihalache (Mirceam) Cris Mihalache (Mirceam)
crussell187 crussell187
DanielVukelich
darkf darkf
devnexen devnexen
Dieho Dieho

View file

@ -303,25 +303,25 @@ if [ -z $SKIP_DOWNLOAD ]; then
# Boost # Boost
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
download "Boost 1.61.0" \ download "Boost 1.61.0" \
"http://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ "https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \
"boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" "boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe"
fi fi
# Bullet # Bullet
download "Bullet 2.86" \ download "Bullet 2.86" \
"http://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \
"Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z"
# FFmpeg # FFmpeg
download "FFmpeg 3.2.4" \ download "FFmpeg 3.2.4" \
"http://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \ "https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \
"ffmpeg-3.2.4-win${BITS}.zip" \ "ffmpeg-3.2.4-win${BITS}.zip" \
"http://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \ "https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \
"ffmpeg-3.2.4-dev-win${BITS}.zip" "ffmpeg-3.2.4-dev-win${BITS}.zip"
# MyGUI # MyGUI
download "MyGUI 3.2.2" \ download "MyGUI 3.2.2" \
"http://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \
"MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z"
# OpenAL # OpenAL
@ -331,7 +331,7 @@ if [ -z $SKIP_DOWNLOAD ]; then
# OSG # OSG
download "OpenSceneGraph 3.4.1-scrawl" \ download "OpenSceneGraph 3.4.1-scrawl" \
"http://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \
"OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z"
# Qt # Qt
@ -343,9 +343,9 @@ if [ -z $SKIP_DOWNLOAD ]; then
fi fi
download "Qt 5.7.2" \ download "Qt 5.7.2" \
"http://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ "https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \ "qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
"http://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
"qt-5-install.qs" "qt-5-install.qs"
fi fi
@ -613,8 +613,7 @@ fi
SUFFIX="" SUFFIX=""
fi fi
add_runtime_dlls "$(pwd)/bin/lib"{EGL,GLESv2}${SUFFIX}.dll \ add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
"$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll" add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll"
echo Done. echo Done.

View file

@ -135,6 +135,8 @@ if (WIN32)
endif() endif()
# Dependencies # Dependencies
find_package(OpenGL REQUIRED)
if (USE_QT) if (USE_QT)
message(STATUS "Using Qt${DESIRED_QT_VERSION}") message(STATUS "Using Qt${DESIRED_QT_VERSION}")
@ -182,12 +184,6 @@ if (NOT WIN32 AND BUILD_WIZARD) # windows users can just run the morrowind insta
set(OPENMW_USE_UNSHIELD TRUE) set(OPENMW_USE_UNSHIELD TRUE)
endif() endif()
option(OPENGL_ES "enable opengl es support" FALSE )
if (OPENGL_ES)
add_definitions(-DOPENGL_ES)
endif(OPENGL_ES)
# Fix for not visible pthreads functions for linker with glibc 2.15 # Fix for not visible pthreads functions for linker with glibc 2.15
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
find_package (Threads) find_package (Threads)
@ -505,8 +501,8 @@ if(WIN32)
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md")
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}") SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe") SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe")
SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe") SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")

View file

@ -3,7 +3,7 @@ How to contribute to OpenMW
Not sure what to do with all your free time? Pick out a task from here: Not sure what to do with all your free time? Pick out a task from here:
http://bugs.openmw.org/ https://bugs.openmw.org/
Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first. Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first.

View file

@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school, You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>. <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>. <https://www.gnu.org/philosophy/why-not-lgpl.html>.

View file

@ -9,7 +9,7 @@ OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction
* Version: 0.43.0 * Version: 0.43.0
* License: GPLv3 (see [LICENSE](https://github.com/OpenMW/openmw/blob/master/LICENSE) for more information) * License: GPLv3 (see [LICENSE](https://github.com/OpenMW/openmw/blob/master/LICENSE) for more information)
* Website: http://www.openmw.org * Website: https://www.openmw.org
* IRC: #openmw on irc.freenode.net * IRC: #openmw on irc.freenode.net
Font Licenses: Font Licenses:
@ -30,8 +30,8 @@ Getting Started
* [Build from source](https://wiki.openmw.org/index.php?title=Development_Environment_Setup) * [Build from source](https://wiki.openmw.org/index.php?title=Development_Environment_Setup)
* [Testing the game](https://wiki.openmw.org/index.php?title=Testing) * [Testing the game](https://wiki.openmw.org/index.php?title=Testing)
* [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted) * [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted)
* [Report a bug](http://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug! * [Report a bug](https://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug!
* [Known issues](http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker) * [Known issues](https://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker)
The data path The data path
------------- -------------

View file

@ -20,7 +20,7 @@ bool Launcher::AdvancedPage::loadSettings()
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
loadSettingBool(showMeleeInfoCheckBox, "show enchant chance", "Game"); loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
@ -35,9 +35,11 @@ bool Launcher::AdvancedPage::loadSettings()
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input");
// Other Settings // Saves Settings
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves"));
// Other Settings
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
screenshotFormatComboBox->addItem(screenshotFormatString); screenshotFormatComboBox->addItem(screenshotFormatString);
@ -56,7 +58,7 @@ void Launcher::AdvancedPage::saveSettings()
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
saveSettingBool(showMeleeInfoCheckBox, "show enchant chance", "Game"); saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
@ -69,9 +71,14 @@ void Launcher::AdvancedPage::saveSettings()
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input");
// Other Settings // Saves Settings
saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
int maximumQuicksaves = maximumQuicksavesComboBox->value();
if (maximumQuicksaves != mEngineSettings.getInt("max quicksaves", "Saves")) {
mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves);
}
// Other Settings
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
mEngineSettings.setString("screenshot format", "General", screenshotFormatString); mEngineSettings.setString("screenshot format", "General", screenshotFormatString);

View file

@ -106,7 +106,7 @@ CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
/// \todo remove this label once we are feature complete and convinced that this thing is /// \todo remove this label once we are feature complete and convinced that this thing is
/// working properly. /// working properly.
QLabel *warning = new QLabel ("<font color=Red>WARNING: OpenMW-CS is in alpha stage.<p>The editor is not feature complete and not sufficiently tested.<br>In theory your data should be safe. But we strongly advice to make backups regularly if you are working with live data.</font color>"); QLabel *warning = new QLabel ("<font color=Red>WARNING: OpenMW-CS is in alpha stage.<p>The editor is not feature complete and not sufficiently tested.<br>In theory your data should be safe. But we strongly advise to make backups regularly if you are working with live data.</font color>");
QFont font; QFont font;
font.setPointSize (12); font.setPointSize (12);

View file

@ -89,7 +89,7 @@ add_openmw_dir (mwmechanics
) )
add_openmw_dir (mwstate add_openmw_dir (mwstate
statemanagerimp charactermanager character statemanagerimp charactermanager character quicksavemanager
) )
add_openmw_dir (mwbase add_openmw_dir (mwbase
@ -222,4 +222,3 @@ endif (MSVC)
if (WIN32) if (WIN32)
INSTALL(TARGETS openmw RUNTIME DESTINATION ".") INSTALL(TARGETS openmw RUNTIME DESTINATION ".")
endif (WIN32) endif (WIN32)

View file

@ -35,28 +35,11 @@ int Java_org_libsdl_app_SDLActivity_isMouseShown(JNIEnv *env, jclass cls, jobjec
return SDL_ShowCursor(SDL_QUERY); return SDL_ShowCursor(SDL_QUERY);
} }
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) {
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls,
jobject obj) {
setenv("OPENMW_DECOMPRESS_TEXTURES", "1", 1); setenv("OPENMW_DECOMPRESS_TEXTURES", "1", 1);
SDL_Android_Init(env, cls);
SDL_SetMainReady();
// On Android, we use a virtual controller with guid="Virtual" // On Android, we use a virtual controller with guid="Virtual"
SDL_GameControllerAddMapping("5669727475616c000000000000000000,Virtual,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4"); SDL_GameControllerAddMapping("5669727475616c000000000000000000,Virtual,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4");
/* Run the application code! */ return 0;
int status;
status = main(argcData+1, argvData);
releaseArgv();
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
/* exit(status); */
return status;
} }

View file

@ -39,6 +39,7 @@ namespace MWBase
class ResponseCallback class ResponseCallback
{ {
public: public:
virtual ~ResponseCallback() = default;
virtual void addResponse(const std::string& title, const std::string& text) = 0; virtual void addResponse(const std::string& title, const std::string& text) = 0;
}; };

View file

@ -337,7 +337,7 @@ namespace MWBase
/// Cycle to next or previous weapon /// Cycle to next or previous weapon
virtual void cycleWeapon(bool next) = 0; virtual void cycleWeapon(bool next) = 0;
virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f) = 0; virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f) = 0;
// In WindowManager for now since there isn't a VFS singleton // In WindowManager for now since there isn't a VFS singleton
virtual std::string correctIconPath(const std::string& path) = 0; virtual std::string correctIconPath(const std::string& path) = 0;

View file

@ -491,12 +491,14 @@ namespace MWBase
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0; const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0;
virtual void applyLoopingParticles(const MWWorld::Ptr& ptr) = 0;
virtual const std::vector<std::string>& getContentFiles() const = 0; virtual const std::vector<std::string>& getContentFiles() const = 0;
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0; virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
// Are we in an exterior or pseudo-exterior cell and it's night? // Allow NPCs to use torches?
virtual bool isDark() const = 0; virtual bool useTorches() const = 0;
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0; virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;

View file

@ -233,24 +233,6 @@ namespace MWClass
if (!(ref->mBase->mData.mFlags & ESM::Light::Carry)) if (!(ref->mBase->mData.mFlags & ESM::Light::Carry))
return std::make_pair(0,""); return std::make_pair(0,"");
const MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc);
MWWorld::ConstContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(weapon == invStore.end())
return std::make_pair(1,"");
/// \todo the 2h check is repeated many times; put it in a function
if(weapon->getTypeName() == typeid(ESM::Weapon).name() &&
(weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow))
{
return std::make_pair(3,"");
}
return std::make_pair(1,""); return std::make_pair(1,"");
} }

View file

@ -83,8 +83,9 @@ namespace MWClass
if (ptr.getCellRef().getSoul() != "") if (ptr.getCellRef().getSoul() != "")
{ {
const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(ref->mRef.getSoul()); const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ref->mRef.getSoul());
value *= creature->mData.mSoul; if (creature)
value *= creature->mData.mSoul;
} }
return value; return value;
@ -148,8 +149,9 @@ namespace MWClass
if (ref->mRef.getSoul() != "") if (ref->mRef.getSoul() != "")
{ {
const ESM::Creature *creature = store.get<ESM::Creature>().find(ref->mRef.getSoul()); const ESM::Creature *creature = store.get<ESM::Creature>().search(ref->mRef.getSoul());
info.caption += " (" + creature->mName + ")"; if (creature)
info.caption += " (" + creature->mName + ")";
} }
std::string text; std::string text;
@ -210,7 +212,7 @@ namespace MWClass
std::shared_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr) const std::shared_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr) const
{ {
if (ptr.getCellRef().getSoul().empty()) if (ptr.getCellRef().getSoul().empty() || !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ptr.getCellRef().getSoul()))
return std::shared_ptr<MWWorld::Action>(new MWWorld::NullAction()); return std::shared_ptr<MWWorld::Action>(new MWWorld::NullAction());
else else
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionSoulgem(ptr)); return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionSoulgem(ptr));

View file

@ -83,8 +83,10 @@ namespace MWDialogue
if (i->mTopic == id && i->mInfoId == infoId) if (i->mTopic == id && i->mInfoId == infoId)
{ {
if (getJournalIndex(id) < index) if (getJournalIndex(id) < index)
{
setJournalIndex(id, index); setJournalIndex(id, index);
MWBase::Environment::get().getWindowManager()->messageBox ("#{sJournalEntry}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sJournalEntry}");
}
return; return;
} }

View file

@ -892,7 +892,7 @@ protected:
public: public:
typedef TypesetBookImpl::StyleImpl Style; typedef TypesetBookImpl::StyleImpl Style;
typedef std::map <TextFormat::Id, TextFormat*> ActiveTextFormats; typedef std::map <TextFormat::Id, std::unique_ptr<TextFormat>> ActiveTextFormats;
int mViewTop; int mViewTop;
int mViewBottom; int mViewBottom;
@ -1048,7 +1048,7 @@ public:
{ {
if (mNode != NULL) if (mNode != NULL)
i->second->destroyDrawItem (mNode); i->second->destroyDrawItem (mNode);
delete i->second; i->second.reset();
} }
mActiveTextFormats.clear (); mActiveTextFormats.clear ();
@ -1115,11 +1115,11 @@ public:
if (j == this_->mActiveTextFormats.end ()) if (j == this_->mActiveTextFormats.end ())
{ {
TextFormat * textFormat = new TextFormat (Font, this_); std::unique_ptr<TextFormat> textFormat(new TextFormat (Font, this_));
textFormat->mTexture = Font->getTextureFont (); textFormat->mTexture = Font->getTextureFont ();
j = this_->mActiveTextFormats.insert (std::make_pair (Font, textFormat)).first; j = this_->mActiveTextFormats.insert (std::make_pair (Font, std::move(textFormat))).first;
} }
j->second->mCountVertex += run.mPrintableChars * 6; j->second->mCountVertex += run.mPrintableChars * 6;

View file

@ -200,7 +200,7 @@ namespace MWGui
{ {
if ((mCurrentPage+1)*2 < mPages.size()) if ((mCurrentPage+1)*2 < mPages.size())
{ {
MWBase::Environment::get().getWindowManager()->playSound("book page2"); MWBase::Environment::get().getWindowManager()->playSound("book page2", true);
++mCurrentPage; ++mCurrentPage;
@ -211,7 +211,7 @@ namespace MWGui
{ {
if (mCurrentPage > 0) if (mCurrentPage > 0)
{ {
MWBase::Environment::get().getWindowManager()->playSound("book page"); MWBase::Environment::get().getWindowManager()->playSound("book page", true);
--mCurrentPage; --mCurrentPage;

View file

@ -1,5 +1,7 @@
#include "companionwindow.hpp" #include "companionwindow.hpp"
#include <cmath>
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -129,7 +131,7 @@ void CompanionWindow::updateEncumbranceBar()
return; return;
float capacity = mPtr.getClass().getCapacity(mPtr); float capacity = mPtr.getClass().getCapacity(mPtr);
float encumbrance = mPtr.getClass().getEncumbrance(mPtr); float encumbrance = mPtr.getClass().getEncumbrance(mPtr);
mEncumbranceBar->setValue(static_cast<int>(encumbrance), static_cast<int>(capacity)); mEncumbranceBar->setValue(std::ceil(encumbrance), static_cast<int>(capacity));
if (mModel && mModel->hasProfit(mPtr)) if (mModel && mModel->hasProfit(mPtr))
{ {

View file

@ -1,5 +1,6 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include <cmath>
#include <stdexcept> #include <stdexcept>
#include <MyGUI_Window.h> #include <MyGUI_Window.h>
@ -598,7 +599,7 @@ namespace MWGui
float capacity = player.getClass().getCapacity(player); float capacity = player.getClass().getCapacity(player);
float encumbrance = player.getClass().getEncumbrance(player); float encumbrance = player.getClass().getEncumbrance(player);
mTradeModel->adjustEncumbrance(encumbrance); mTradeModel->adjustEncumbrance(encumbrance);
mEncumbranceBar->setValue(static_cast<int>(encumbrance), static_cast<int>(capacity)); mEncumbranceBar->setValue(std::ceil(encumbrance), static_cast<int>(capacity));
} }
void InventoryWindow::onFrame(float dt) void InventoryWindow::onFrame(float dt)

View file

@ -16,8 +16,13 @@ namespace
{ {
if (count == 1) if (count == 1)
return ""; return "";
if (count > 9999)
return MyGUI::utility::toString(int(count/1000.f)) + "k"; if (count > 999999999)
return MyGUI::utility::toString(count/1000000000) + "b";
else if (count > 999999)
return MyGUI::utility::toString(count/1000000) + "m";
else if (count > 9999)
return MyGUI::utility::toString(count/1000) + "k";
else else
return MyGUI::utility::toString(count); return MyGUI::utility::toString(count);
} }

View file

@ -616,7 +616,7 @@ namespace
if (page+2 < book->pageCount()) if (page+2 < book->pageCount())
{ {
MWBase::Environment::get().getWindowManager()->playSound("book page"); MWBase::Environment::get().getWindowManager()->playSound("book page", true);
page += 2; page += 2;
updateShowingPages (); updateShowingPages ();
@ -634,7 +634,7 @@ namespace
if(page >= 2) if(page >= 2)
{ {
MWBase::Environment::get().getWindowManager()->playSound("book page"); MWBase::Environment::get().getWindowManager()->playSound("book page", true);
page -= 2; page -= 2;
updateShowingPages (); updateShowingPages ();

View file

@ -39,6 +39,7 @@ void getKeyFocusWidgets(MyGUI::Widget* parent, std::vector<MyGUI::Widget*>& resu
KeyboardNavigation::KeyboardNavigation() KeyboardNavigation::KeyboardNavigation()
: mCurrentFocus(nullptr) : mCurrentFocus(nullptr)
, mModalWindow(nullptr) , mModalWindow(nullptr)
, mEnabled(true)
{ {
MyGUI::WidgetManager::getInstance().registerUnlinker(this); MyGUI::WidgetManager::getInstance().registerUnlinker(this);
} }
@ -101,6 +102,9 @@ bool isRootParent(MyGUI::Widget* widget, MyGUI::Widget* root)
void KeyboardNavigation::onFrame() void KeyboardNavigation::onFrame()
{ {
if (!mEnabled)
return;
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
if (focus == mCurrentFocus) if (focus == mCurrentFocus)
@ -150,6 +154,11 @@ void KeyboardNavigation::setModalWindow(MyGUI::Widget *window)
mModalWindow = window; mModalWindow = window;
} }
void KeyboardNavigation::setEnabled(bool enabled)
{
mEnabled = enabled;
}
enum Direction enum Direction
{ {
D_Left, D_Left,
@ -162,6 +171,9 @@ enum Direction
bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text) bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
{ {
if (!mEnabled)
return false;
switch (key.getValue()) switch (key.getValue())
{ {
case MyGUI::KeyCode::ArrowLeft: case MyGUI::KeyCode::ArrowLeft:

View file

@ -28,6 +28,8 @@ namespace MWGui
void setModalWindow(MyGUI::Widget* window); void setModalWindow(MyGUI::Widget* window);
void setEnabled(bool enabled);
private: private:
bool switchFocus(int direction, bool wrap); bool switchFocus(int direction, bool wrap);
@ -40,6 +42,8 @@ namespace MWGui
MyGUI::Widget* mCurrentFocus; MyGUI::Widget* mCurrentFocus;
MyGUI::Widget* mModalWindow; MyGUI::Widget* mModalWindow;
bool mEnabled;
}; };
} }

View file

@ -208,7 +208,7 @@ namespace MWGui
if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted)) if ((mFilter & Filter_OnlyEnchanted) && !(item.mFlags & ItemStack::Flag_Enchanted))
return false; return false;
if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name() if ((mFilter & Filter_OnlyChargedSoulstones) && (base.getTypeName() != typeid(ESM::Miscellaneous).name()
|| base.getCellRef().getSoul() == "")) || base.getCellRef().getSoul() == "" || !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(base.getCellRef().getSoul())))
return false; return false;
if ((mFilter & Filter_OnlyRepairTools) && (base.getTypeName() != typeid(ESM::Repair).name())) if ((mFilter & Filter_OnlyRepairTools) && (base.getTypeName() != typeid(ESM::Repair).name()))
return false; return false;

View file

@ -4,6 +4,8 @@
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -72,7 +74,10 @@ namespace MWGui
MWWorld::ActionTeleport::getFollowersToTeleport(player, followers); MWWorld::ActionTeleport::getFollowersToTeleport(player, followers);
// Apply followers cost, in vanilla one follower travels for free // Apply followers cost, in vanilla one follower travels for free
price *= std::max(1, static_cast<int>(followers.size())); if (Settings::Manager::getBool("charge for every follower travelling", "Game"))
price *= 1 + static_cast<int>(followers.size());
else
price *= std::max(1, static_cast<int>(followers.size()));
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>("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); toAdd->setEnabled(price <= playerGold);

View file

@ -237,7 +237,10 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
MyGUI::ResourceManager::getInstance().load("core.xml"); MyGUI::ResourceManager::getInstance().load("core.xml");
bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI");
mKeyboardNavigation.reset(new KeyboardNavigation()); mKeyboardNavigation.reset(new KeyboardNavigation());
mKeyboardNavigation->setEnabled(keyboardNav);
Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav);
mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer); mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer);
mWindows.push_back(mLoadingScreen); mWindows.push_back(mLoadingScreen);
@ -1916,11 +1919,16 @@ namespace MWGui
mInventoryWindow->cycle(next); mInventoryWindow->cycle(next);
} }
void WindowManager::playSound(const std::string& soundId, float volume, float pitch) void WindowManager::playSound(const std::string& soundId, bool preventOverlapping, float volume, float pitch)
{ {
if (soundId.empty()) if (soundId.empty())
return; return;
MWBase::Environment::get().getSoundManager()->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv);
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
if (preventOverlapping && sndmgr->getSoundPlaying(MWWorld::Ptr(), soundId))
return;
sndmgr->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv);
} }
void WindowManager::updateSpellWindow() void WindowManager::updateSpellWindow()

View file

@ -366,7 +366,7 @@ namespace MWGui
/// Cycle to next or previous weapon /// Cycle to next or previous weapon
virtual void cycleWeapon(bool next); virtual void cycleWeapon(bool next);
virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f); virtual void playSound(const std::string& soundId, bool preventOverlapping = false, float volume = 1.f, float pitch = 1.f);
// In WindowManager for now since there isn't a VFS singleton // In WindowManager for now since there isn't a VFS singleton
virtual std::string correctIconPath(const std::string& path); virtual std::string correctIconPath(const std::string& path);

View file

@ -524,30 +524,29 @@ namespace MWInput
isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25; isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25;
if(triedToMove) resetIdleTime(); if(triedToMove) resetIdleTime();
if (actionIsActive(A_MoveLeft)) if (actionIsActive(A_MoveLeft) && !actionIsActive(A_MoveRight))
{ {
triedToMove = true; triedToMove = true;
mPlayer->setLeftRight (-1); mPlayer->setLeftRight (-1);
} }
else if (actionIsActive(A_MoveRight)) else if (actionIsActive(A_MoveRight) && !actionIsActive(A_MoveLeft))
{ {
triedToMove = true; triedToMove = true;
mPlayer->setLeftRight (1); mPlayer->setLeftRight (1);
} }
if (actionIsActive(A_MoveForward)) if (actionIsActive(A_MoveForward) && !actionIsActive(A_MoveBackward))
{ {
triedToMove = true; triedToMove = true;
mPlayer->setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1); mPlayer->setForwardBackward (1);
} }
else if (actionIsActive(A_MoveBackward)) else if (actionIsActive(A_MoveBackward) && !actionIsActive(A_MoveForward))
{ {
triedToMove = true; triedToMove = true;
mPlayer->setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1); mPlayer->setForwardBackward (-1);
} }
else if(mPlayer->getAutoMove()) else if(mPlayer->getAutoMove())
{ {
triedToMove = true; triedToMove = true;

View file

@ -391,7 +391,7 @@ namespace MWMechanics
{ {
// Player followers and escorters with high fight should not initiate combat with the player or with // Player followers and escorters with high fight should not initiate combat with the player or with
// other player followers or escorters // other player followers or escorters
if (std::find(playerAllies.begin(), playerAllies.end(), actor1) == playerAllies.end()) if (!isPlayerFollowerOrEscorter)
aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2); aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2);
} }
} }
@ -900,7 +900,7 @@ namespace MWMechanics
stats.setTimeToStartDrowning(fHoldBreathTime); stats.setTimeToStartDrowning(fHoldBreathTime);
} }
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip)
{ {
bool isPlayer = (ptr == getPlayer()); bool isPlayer = (ptr == getPlayer());
@ -922,7 +922,7 @@ namespace MWMechanics
} }
} }
if (MWBase::Environment::get().getWorld()->isDark()) if (mayEquip)
{ {
if (torch != inventoryStore.end()) if (torch != inventoryStore.end())
{ {
@ -931,16 +931,11 @@ namespace MWMechanics
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light. // For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
inventoryStore.unequipItem(*heldIter, ptr); inventoryStore.unequipItem(*heldIter, ptr);
// Also unequip twohanded weapons which conflict with anything in CarriedLeft
if (torch->getClass().canBeEquipped(*torch, ptr).first == 3)
inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr);
} }
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
// If we have a torch and can equip it (left slot free, no // If we have a torch and can equip it, then equip it now.
// twohanded weapon in right slot), then equip it now.
if (heldIter == inventoryStore.end() if (heldIter == inventoryStore.end()
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1) && torch->getClass().canBeEquipped(*torch, ptr).first == 1)
{ {
@ -997,7 +992,7 @@ namespace MWMechanics
} }
} }
void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration) void Actors::updateCrimePursuit(const MWWorld::Ptr& ptr, float duration)
{ {
MWWorld::Ptr player = getPlayer(); MWWorld::Ptr player = getPlayer();
if (ptr != player && ptr.getClass().isNpc()) if (ptr != player && ptr.getClass().isNpc())
@ -1204,6 +1199,9 @@ namespace MWMechanics
if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0; if (mTimerDisposeSummonsCorpses >= 0.2f) mTimerDisposeSummonsCorpses = 0;
if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0; if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0;
// show torches only when there are darkness and no precipitations
bool showTorches = MWBase::Environment::get().getWorld()->useTorches();
MWWorld::Ptr player = getPlayer(); MWWorld::Ptr player = getPlayer();
/// \todo move update logic to Actor class where appropriate /// \todo move update logic to Actor class where appropriate
@ -1287,7 +1285,7 @@ namespace MWMechanics
} }
if (iter->first.getClass().isNpc() && iter->first != player) if (iter->first.getClass().isNpc() && iter->first != player)
updateCrimePersuit(iter->first, duration); updateCrimePursuit(iter->first, duration);
if (iter->first != player) if (iter->first != player)
{ {
@ -1302,7 +1300,7 @@ namespace MWMechanics
updateNpc(iter->first, duration); updateNpc(iter->first, duration);
if (timerUpdateEquippedLight == 0) if (timerUpdateEquippedLight == 0)
updateEquippedLight(iter->first, updateEquippedLightInterval); updateEquippedLight(iter->first, updateEquippedLightInterval, showTorches);
} }
} }
} }

View file

@ -39,9 +39,9 @@ namespace MWMechanics
void updateDrowning (const MWWorld::Ptr& ptr, float duration); void updateDrowning (const MWWorld::Ptr& ptr, float duration);
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration); void updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip);
void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration); void updateCrimePursuit (const MWWorld::Ptr& ptr, float duration);
void killDeadActors (); void killDeadActors ();

View file

@ -189,7 +189,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
MWWorld::Ptr door = getNearbyDoor(actor, distance); MWWorld::Ptr door = getNearbyDoor(actor, distance);
if (door != MWWorld::Ptr()) if (door != MWWorld::Ptr() && actor.getClass().isBipedal(actor))
{ {
// note: AiWander currently does not open doors // note: AiWander currently does not open doors
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0) if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == 0)
@ -224,7 +224,7 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur
MWBase::Environment::get().getWorld()->activate(door, actor); MWBase::Environment::get().getWorld()->activate(door, actor);
} }
} }
else // any other obstacle (NPC, crate, etc.) else
{ {
mObstacleCheck.takeEvasiveAction(movement); mObstacleCheck.takeEvasiveAction(movement);
} }

View file

@ -14,7 +14,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* version 3 along with this program. If not, see * version 3 along with this program. If not, see
* http://www.gnu.org/licenses/ . * https://www.gnu.org/licenses/ .
*/ */
#include "character.hpp" #include "character.hpp"

View file

@ -1,6 +1,7 @@
#include "combat.hpp" #include "combat.hpp"
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include <components/sceneutil/positionattitudetransform.hpp> #include <components/sceneutil/positionattitudetransform.hpp>
@ -155,7 +156,11 @@ namespace MWMechanics
if (!(weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver if (!(weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver
|| weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Magical)) || weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Magical))
damage *= multiplier; {
if (weapon.getClass().getEnchantment(weapon).empty()
|| !Settings::Manager::getBool("enchanted weapons are magical", "Game"))
damage *= multiplier;
}
if ((weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver) if ((weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver)
&& actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())

View file

@ -242,8 +242,11 @@ namespace MWMechanics
return 0; return 0;
if(mSoulGemPtr.getCellRef().getSoul()=="") if(mSoulGemPtr.getCellRef().getSoul()=="")
return 0; return 0;
const ESM::Creature* soul = store.get<ESM::Creature>().find(mSoulGemPtr.getCellRef().getSoul()); const ESM::Creature* soul = store.get<ESM::Creature>().search(mSoulGemPtr.getCellRef().getSoul());
return soul->mData.mSoul; if(soul)
return soul->mData.mSoul;
else
return 0;
} }
int Enchanting::getMaxEnchantValue() const int Enchanting::getMaxEnchantValue() const

View file

@ -1118,8 +1118,11 @@ namespace MWMechanics
Misc::StringUtils::lowerCaseInPlace(owner.first); Misc::StringUtils::lowerCaseInPlace(owner.first);
if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; {
const MWWorld::Ptr victimRef = MWBase::Environment::get().getWorld()->searchPtr(ownerCellRef->getOwner(), true);
if (victimRef.isEmpty() || !victimRef.getClass().getCreatureStats(victimRef).isDead())
mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count;
}
if (alarm) if (alarm)
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
} }
@ -1442,7 +1445,20 @@ namespace MWMechanics
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back. // Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
// Note: accidental or collateral damage attacks are ignored. // Note: accidental or collateral damage attacks are ignored.
if (!target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue)) if (!target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
startCombat(target, attacker); {
// If an actor has OnPCHitMe declared in his script, his Fight = 0 and the attacker is player,
// he will attack the player only if we will force him (e.g. via StartCombat console command)
bool peaceful = false;
std::string script = target.getClass().getScript(target);
if (!script.empty() && target.getRefData().getLocals().hasVar(script, "onpchitme") && attacker == getPlayer())
{
int fight = std::max(0, target.getClass().getCreatureStats(target).getAiSetting(CreatureStats::AI_Fight).getModified());
peaceful = (fight == 0);
}
if (!peaceful)
startCombat(target, attacker);
}
} }
return true; return true;
@ -1719,11 +1735,11 @@ namespace MWMechanics
{ {
if (werewolf) if (werewolf)
{ {
player->saveSkillsAttributes(); player->saveStats();
player->setWerewolfSkillsAttributes(); player->setWerewolfStats();
} }
else else
player->restoreSkillsAttributes(); player->restoreStats();
} }
// Werewolfs can not cast spells, so we need to unset the prepared spell if there is one. // Werewolfs can not cast spells, so we need to unset the prepared spell if there is one.

View file

@ -214,7 +214,7 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
} }
} }
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress) void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress, bool readBook)
{ {
int base = getSkill (skillIndex).getBase(); int base = getSkill (skillIndex).getBase();
@ -256,9 +256,14 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
MWBase::Environment::get().getWindowManager()->playSound("skillraise"); MWBase::Environment::get().getWindowManager()->playSound("skillraise");
std::stringstream message; std::stringstream message;
if (readBook)
message << std::string("#{sBookSkillMessage}\n");
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "")) message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}") % std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
% static_cast<int> (base); % static_cast<int> (base);
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never); MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never);
if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt()) if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt())

View file

@ -81,7 +81,7 @@ namespace MWMechanics
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f); void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
///< Increase skill by usage. ///< Increase skill by usage.
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress); void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress, bool readBook = false);
int getLevelProgress() const; int getLevelProgress() const;

View file

@ -8,7 +8,7 @@
namespace namespace
{ {
// See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html // See https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
// //
// One of the smallest cost in Seyda Neen is between points 77 & 78: // One of the smallest cost in Seyda Neen is between points 77 & 78:
// pt x y // pt x y

View file

@ -7,6 +7,7 @@
#include <boost/format.hpp> #include <boost/format.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -24,7 +25,6 @@
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
#include "magiceffects.hpp"
#include "npcstats.hpp" #include "npcstats.hpp"
#include "actorutil.hpp" #include "actorutil.hpp"
#include "aifollow.hpp" #include "aifollow.hpp"
@ -489,6 +489,9 @@ namespace MWMechanics
MWBase::Environment::get().getWindowManager()->setEnemy(target); MWBase::Environment::get().getWindowManager()->setEnemy(target);
} }
if (target == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())
magnitudeMult = 0;
// Notify the target actor they've been hit // Notify the target actor they've been hit
if (target != caster && !caster.isEmpty() && magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) if (target != caster && !caster.isEmpty() && magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
target.getClass().onHit(target, 0.0f, true, MWWorld::Ptr(), caster, osg::Vec3f(), true); target.getClass().onHit(target, 0.0f, true, MWWorld::Ptr(), caster, osg::Vec3f(), true);
@ -563,9 +566,12 @@ namespace MWMechanics
ActiveSpells::ActiveEffect effect_ = effect; ActiveSpells::ActiveEffect effect_ = effect;
effect_.mMagnitude *= -1; effect_.mMagnitude *= -1;
absorbEffects.push_back(effect_); absorbEffects.push_back(effect_);
// Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies if (reflected && Settings::Manager::getBool("classic reflect absorb attribute behavior", "Game"))
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
else
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
} }
} }
} }
@ -605,7 +611,6 @@ namespace MWMechanics
std::string texture = magicEffect->mParticle; std::string texture = magicEffect->mParticle;
// TODO: VFX are no longer active after saving/reloading the game
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
// Note: in case of non actor, a free effect should be fine as well // Note: in case of non actor, a free effect should be fine as well
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
@ -873,20 +878,18 @@ namespace MWMechanics
const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster); const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster);
float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult); float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult);
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue); fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
stats.setFatigue(fatigue);
bool fail = false; bool fail = false;
// Check success // Check success
if (!(mCaster == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())) float successChance = getSpellSuccessChance(spell, mCaster);
if (Misc::Rng::roll0to99() >= successChance)
{ {
float successChance = getSpellSuccessChance(spell, mCaster); if (mCaster == getPlayer())
if (Misc::Rng::roll0to99() >= successChance) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
{ fail = true;
if (mCaster == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
fail = true;
}
} }
if (fail) if (fail)
@ -1107,8 +1110,6 @@ namespace MWMechanics
bool receivedMagicDamage = false; bool receivedMagicDamage = false;
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
switch (effectKey.mId) switch (effectKey.mId)
{ {
case ESM::MagicEffect::DamageAttribute: case ESM::MagicEffect::DamageAttribute:
@ -1131,40 +1132,25 @@ namespace MWMechanics
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude); adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude);
break; break;
case ESM::MagicEffect::DamageHealth: case ESM::MagicEffect::DamageHealth:
if (!godmode) receivedMagicDamage = true;
{ adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::DamageMagicka: case ESM::MagicEffect::DamageMagicka:
case ESM::MagicEffect::DamageFatigue: case ESM::MagicEffect::DamageFatigue:
if (!godmode) adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::AbsorbHealth: case ESM::MagicEffect::AbsorbHealth:
if (!godmode) if (magnitude > 0.f)
{ receivedMagicDamage = true;
if (magnitude > 0.f) adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::AbsorbMagicka: case ESM::MagicEffect::AbsorbMagicka:
case ESM::MagicEffect::AbsorbFatigue: case ESM::MagicEffect::AbsorbFatigue:
if (!godmode) adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
break; break;
case ESM::MagicEffect::DisintegrateArmor: case ESM::MagicEffect::DisintegrateArmor:
@ -1187,6 +1173,7 @@ namespace MWMechanics
if (disintegrateSlot(actor, priorities[i], magnitude)) if (disintegrateSlot(actor, priorities[i], magnitude))
break; break;
} }
break; break;
} }
case ESM::MagicEffect::DisintegrateWeapon: case ESM::MagicEffect::DisintegrateWeapon:
@ -1209,12 +1196,9 @@ namespace MWMechanics
if (weather > 1) if (weather > 1)
damageScale *= fMagicSunBlockedMult; damageScale *= fMagicSunBlockedMult;
if (!godmode) adjustDynamicStat(creatureStats, 0, -magnitude * damageScale);
{ if (magnitude * damageScale > 0.f)
adjustDynamicStat(creatureStats, 0, -magnitude * damageScale); receivedMagicDamage = true;
if (magnitude * damageScale > 0.f)
receivedMagicDamage = true;
}
break; break;
} }
@ -1224,12 +1208,8 @@ namespace MWMechanics
case ESM::MagicEffect::FrostDamage: case ESM::MagicEffect::FrostDamage:
case ESM::MagicEffect::Poison: case ESM::MagicEffect::Poison:
{ {
if (!godmode) adjustDynamicStat(creatureStats, 0, -magnitude);
{ receivedMagicDamage = true;
adjustDynamicStat(creatureStats, 0, -magnitude);
receivedMagicDamage = true;
}
break; break;
} }
@ -1310,4 +1290,24 @@ namespace MWMechanics
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString(); return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
} }
void ApplyLoopingParticlesVisitor::visit (MWMechanics::EffectKey key,
const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/,
float /*magnitude*/, float /*remainingTime*/, float /*totalTime*/)
{
const ESM::MagicEffect *magicEffect =
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(key.mId);
const ESM::Static* castStatic;
if (!magicEffect->mHit.empty())
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
else
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
std::string texture = magicEffect->mParticle;
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mActor);
if (anim && loop)
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "", texture);
}
} }

View file

@ -6,6 +6,8 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "magiceffects.hpp"
namespace ESM namespace ESM
{ {
struct Spell; struct Spell;
@ -119,6 +121,21 @@ namespace MWMechanics
bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
}; };
class ApplyLoopingParticlesVisitor : public EffectSourceVisitor
{
private:
MWWorld::Ptr mActor;
public:
ApplyLoopingParticlesVisitor(const MWWorld::Ptr& actor)
: mActor(actor)
{
}
virtual void visit (MWMechanics::EffectKey key,
const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/,
float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1);
};
} }
#endif #endif

View file

@ -13,7 +13,6 @@
#include <BulletCollision/CollisionDispatch/btCollisionObject.h> #include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h> #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h> #include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h> #include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
#include <LinearMath/btQuickprof.h> #include <LinearMath/btQuickprof.h>

View file

@ -8,6 +8,7 @@
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/ComputeBoundsVisitor> #include <osg/ComputeBoundsVisitor>
#include <osg/LightSource> #include <osg/LightSource>
#include <osg/PolygonMode>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
@ -174,6 +175,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
camera->setNodeMask(Mask_RenderToTexture); camera->setNodeMask(Mask_RenderToTexture);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet; osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE);
// assign large value to effectively turn off fog // assign large value to effectively turn off fog
// shaders don't respect glDisable(GL_FOG) // shaders don't respect glDisable(GL_FOG)

View file

@ -51,6 +51,16 @@
#include "terrainstorage.hpp" #include "terrainstorage.hpp"
#include "util.hpp" #include "util.hpp"
namespace
{
float DLLandFogStart;
float DLLandFogEnd;
float DLUnderwaterFogStart;
float DLUnderwaterFogEnd;
float DLInteriorFogStart;
float DLInteriorFogEnd;
}
namespace MWRender namespace MWRender
{ {
@ -173,14 +183,18 @@ namespace MWRender
, mResourceSystem(resourceSystem) , mResourceSystem(resourceSystem)
, mWorkQueue(workQueue) , mWorkQueue(workQueue)
, mUnrefQueue(new SceneUtil::UnrefQueue) , mUnrefQueue(new SceneUtil::UnrefQueue)
, mFogDepth(0.f) , mLandFogStart(0.f)
, mLandFogEnd(std::numeric_limits<float>::max())
, mUnderwaterFogStart(0.f)
, mUnderwaterFogEnd(std::numeric_limits<float>::max())
, mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor")) , mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor"))
, mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight"))
, mUnderwaterFog(0.f)
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
, mNightEyeFactor(0.f) , mNightEyeFactor(0.f)
, mFieldOfViewOverride(0.f) , mDistantFog(false)
, mDistantTerrain(false)
, mFieldOfViewOverridden(false) , mFieldOfViewOverridden(false)
, mFieldOfViewOverride(0.f)
{ {
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
@ -216,12 +230,20 @@ namespace MWRender
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog");
DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog");
DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog");
DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog");
DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog");
mDistantFog = Settings::Manager::getBool("use distant fog", "Fog");
mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"), mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"),
Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"),
Settings::Manager::getBool("auto use terrain specular maps", "Shaders")); Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
if (distantTerrain) if (mDistantTerrain)
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
else else
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
@ -479,14 +501,44 @@ namespace MWRender
{ {
osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog);
configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color); if(mDistantFog)
{
float density = std::max(0.2f, cell->mAmbi.mFogDensity);
mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density);
mLandFogEnd = DLInteriorFogEnd;
mUnderwaterFogStart = DLUnderwaterFogStart;
mUnderwaterFogEnd = DLUnderwaterFogEnd;
mFogColor = color;
}
else
configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color);
} }
void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color) void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color)
{ {
mFogDepth = fogDepth; if(mDistantFog)
{
mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd);
mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd;
mUnderwaterFogStart = DLUnderwaterFogStart;
mUnderwaterFogEnd = DLUnderwaterFogEnd;
}
else
{
if(fogDepth == 0.0)
{
mLandFogStart = 0.0f;
mLandFogEnd = std::numeric_limits<float>::max();
}
else
{
mLandFogStart = mViewDistance * (1 - fogDepth);
mLandFogEnd = mViewDistance;
}
mUnderwaterFogStart = mViewDistance * (1 - underwaterFog);
mUnderwaterFogEnd = mViewDistance;
}
mFogColor = color; mFogColor = color;
mUnderwaterFog = underwaterFog;
} }
SkyManager* RenderingManager::getSkyManager() SkyManager* RenderingManager::getSkyManager()
@ -517,23 +569,15 @@ namespace MWRender
float viewDistance = mViewDistance; float viewDistance = mViewDistance;
viewDistance = std::min(viewDistance, 6666.f); viewDistance = std::min(viewDistance, 6666.f);
setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight)); setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight));
mStateUpdater->setFogStart(viewDistance * (1 - mUnderwaterFog)); mStateUpdater->setFogStart(mUnderwaterFogStart);
mStateUpdater->setFogEnd(viewDistance); mStateUpdater->setFogEnd(mUnderwaterFogEnd);
} }
else else
{ {
setFogColor(mFogColor); setFogColor(mFogColor);
if (mFogDepth == 0.f) mStateUpdater->setFogStart(mLandFogStart);
{ mStateUpdater->setFogEnd(mLandFogEnd);
mStateUpdater->setFogStart(0.f);
mStateUpdater->setFogEnd(std::numeric_limits<float>::max());
}
else
{
mStateUpdater->setFogStart(mViewDistance * (1 - mFogDepth));
mStateUpdater->setFogEnd(mViewDistance);
}
} }
} }
@ -960,7 +1004,8 @@ namespace MWRender
else if (it->first == "Camera" && it->second == "viewing distance") else if (it->first == "Camera" && it->second == "viewing distance")
{ {
mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
mStateUpdater->setFogEnd(mViewDistance); if(!mDistantFog)
mStateUpdater->setFogEnd(mViewDistance);
updateProjectionMatrix(); updateProjectionMatrix();
} }
else if (it->first == "General" && (it->second == "texture filter" || else if (it->first == "General" && (it->second == "texture filter" ||

View file

@ -106,7 +106,7 @@ namespace MWRender
void configureAmbient(const ESM::Cell* cell); void configureAmbient(const ESM::Cell* cell);
void configureFog(const ESM::Cell* cell); void configureFog(const ESM::Cell* cell);
void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour); void configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour);
void addCell(const MWWorld::CellStore* store); void addCell(const MWWorld::CellStore* store);
void removeCell(const MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store);
@ -241,10 +241,12 @@ namespace MWRender
osg::ref_ptr<StateUpdater> mStateUpdater; osg::ref_ptr<StateUpdater> mStateUpdater;
float mFogDepth; float mLandFogStart;
float mLandFogEnd;
float mUnderwaterFogStart;
float mUnderwaterFogEnd;
osg::Vec4f mUnderwaterColor; osg::Vec4f mUnderwaterColor;
float mUnderwaterWeight; float mUnderwaterWeight;
float mUnderwaterFog;
float mUnderwaterIndoorFog; float mUnderwaterIndoorFog;
osg::Vec4f mFogColor; osg::Vec4f mFogColor;
@ -253,8 +255,10 @@ namespace MWRender
float mNearClip; float mNearClip;
float mViewDistance; float mViewDistance;
bool mDistantFog : 1;
bool mDistantTerrain : 1;
bool mFieldOfViewOverridden : 1;
float mFieldOfViewOverride; float mFieldOfViewOverride;
bool mFieldOfViewOverridden;
float mFieldOfView; float mFieldOfView;
float mFirstPersonFieldOfView; float mFirstPersonFieldOfView;

View file

@ -65,6 +65,9 @@ namespace MWRender
float mFogDepth; float mFogDepth;
float mDLFogFactor;
float mDLFogOffset;
float mWindSpeed; float mWindSpeed;
float mCloudSpeed; float mCloudSpeed;

View file

@ -503,13 +503,11 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
// use a shader to render the simple water, ensuring that fog is applied per pixel as required. // use a shader to render the simple water, ensuring that fog is applied per pixel as required.
// this could be removed if a more detailed water mesh, using some sort of paging solution, is implemented. // this could be removed if a more detailed water mesh, using some sort of paging solution, is implemented.
#if !defined(OPENGL_ES) && !defined(ANDROID)
Resource::SceneManager* sceneManager = mResourceSystem->getSceneManager(); Resource::SceneManager* sceneManager = mResourceSystem->getSceneManager();
bool oldValue = sceneManager->getForceShaders(); bool oldValue = sceneManager->getForceShaders();
sceneManager->setForceShaders(true); sceneManager->setForceShaders(true);
sceneManager->recreateShaders(node); sceneManager->recreateShaders(node);
sceneManager->setForceShaders(oldValue); sceneManager->setForceShaders(oldValue);
#endif
} }
void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, Refraction* refraction) void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, Refraction* refraction)

View file

@ -454,7 +454,13 @@ namespace MWScript
store.get<ESM::Creature>().find(creature); // This line throws an exception if it can't find the creature store.get<ESM::Creature>().find(creature); // This line throws an exception if it can't find the creature
MWWorld::Ptr item = *ptr.getClass().getContainerStore(ptr).add(gem, 1, ptr); MWWorld::Ptr item = *ptr.getClass().getContainerStore(ptr).add(gem, 1, ptr);
// Set the soul on just one of the gems, not the whole stack
item.getContainerStore()->unstack(item, ptr);
item.getCellRef().setSoul(creature); item.getCellRef().setSoul(creature);
// Restack the gem with other gems with the same soul
item.getContainerStore()->restack(item);
} }
}; };

View file

@ -15,7 +15,7 @@
* License along with this library; if not, write to the * License along with this library; if not, write to the
* Free Software Foundation, Inc., * Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html * Or go to https://www.gnu.org/copyleft/lgpl.html
*/ */
#ifndef AL_ALEXT_H #ifndef AL_ALEXT_H

View file

@ -21,7 +21,7 @@ extern "C"
// From version 54.56 binkaudio encoding format changed from S16 to FLTP. See: // From version 54.56 binkaudio encoding format changed from S16 to FLTP. See:
// https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d // https://gitorious.org/ffmpeg/ffmpeg/commit/7bfd1766d1c18f07b0a2dd042418a874d49ea60d
// http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872 // https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=872
#include <libswresample/swresample.h> #include <libswresample/swresample.h>
} }

View file

@ -0,0 +1,38 @@
#include "quicksavemanager.hpp"
MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, unsigned int maxSaves)
{
this->mSaveName = saveName;
this->mMaxSaves = maxSaves;
this->mOldestSlotVisited = NULL;
this->mSlotsVisited = 0;
}
void MWState::QuickSaveManager::visitSave(const Slot *saveSlot)
{
if(mSaveName == saveSlot->mProfile.mDescription)
{
++mSlotsVisited;
if(isOldestSave(saveSlot))
mOldestSlotVisited = saveSlot;
}
}
bool MWState::QuickSaveManager::isOldestSave(const Slot *compare)
{
if(mOldestSlotVisited == NULL)
return true;
return (compare->mTimeStamp <= mOldestSlotVisited->mTimeStamp);
}
bool MWState::QuickSaveManager::shouldCreateNewSlot()
{
return (mSlotsVisited < mMaxSaves);
}
const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot()
{
if(shouldCreateNewSlot())
return NULL;
return mOldestSlotVisited;
}

View file

@ -0,0 +1,35 @@
#ifndef GAME_STATE_QUICKSAVEMANAGER_H
#define GAME_STATE_QUICKSAVEMANAGER_H
#include <string>
#include "character.hpp"
#include "../mwbase/statemanager.hpp"
namespace MWState{
class QuickSaveManager{
std::string mSaveName;
unsigned int mMaxSaves;
unsigned int mSlotsVisited;
const Slot *mOldestSlotVisited;
private:
bool shouldCreateNewSlot();
bool isOldestSave(const Slot *compare);
public:
QuickSaveManager(std::string &saveName, unsigned int maxSaves);
///< A utility class to manage multiple quicksave slots
///
/// \param saveName The name of the save ("QuickSave", "AutoSave", etc)
/// \param maxSaves The maximum number of save slots to create before recycling old ones
void visitSave(const Slot *saveSlot);
///< Visits the given \a slot \a
const Slot *getNextQuickSaveSlot();
///< Get the slot that the next quicksave should use.
///
///\return Either the oldest quicksave slot visited, or NULL if a new slot can be made
};
}
#endif

View file

@ -37,6 +37,8 @@
#include "../mwscript/globalscripts.hpp" #include "../mwscript/globalscripts.hpp"
#include "quicksavemanager.hpp"
void MWState::StateManager::cleanup (bool force) void MWState::StateManager::cleanup (bool force)
{ {
if (mState!=State_NoGame || force) if (mState!=State_NoGame || force)
@ -324,20 +326,25 @@ void MWState::StateManager::quickSave (std::string name)
return; return;
} }
const Slot* slot = NULL; int maxSaves = Settings::Manager::getInt("max quicksaves", "Saves");
Character* currentCharacter = getCurrentCharacter(); //Get current character if(maxSaves < 1)
maxSaves = 1;
Character* currentCharacter = getCurrentCharacter(); //Get current character
QuickSaveManager saveFinder = QuickSaveManager(name, maxSaves);
//Find quicksave slot
if (currentCharacter) if (currentCharacter)
{ {
for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it) for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it)
{ {
if (it->mProfile.mDescription == name) //Visiting slots allows the quicksave finder to find the oldest quicksave
slot = &*it; saveFinder.visitSave(&*it);
} }
} }
saveGame(name, slot); //Once all the saves have been visited, the save finder can tell us which
//one to replace (or create)
saveGame(name, saveFinder.getNextQuickSaveSlot());
} }
void MWState::StateManager::loadGame(const std::string& filepath) void MWState::StateManager::loadGame(const std::string& filepath)

View file

@ -52,7 +52,7 @@ namespace MWWorld
playerRef->mBase->mClass playerRef->mBase->mClass
); );
npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true); npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true, true);
npcStats.flagAsUsed (ref->mBase->mId); npcStats.flagAsUsed (ref->mBase->mId);
} }

View file

@ -256,11 +256,7 @@ bool MWWorld::ContainerStore::stacks(const ConstPtr& ptr1, const ConstPtr& ptr2)
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string &id, int count, const Ptr &actorPtr) MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string &id, int count, const Ptr &actorPtr)
{ {
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count);
// a bit pointless to set owner for the player return add(ref.getPtr(), count, actorPtr, true);
if (actorPtr != MWMechanics::getPlayer())
return add(ref.getPtr(), count, actorPtr, true);
else
return add(ref.getPtr(), count, actorPtr, false);
} }
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner) MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner)

View file

@ -48,6 +48,12 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state)
} }
mClass->readAdditionalState (ptr, state); mClass->readAdditionalState (ptr, state);
if (!mRef.getSoul().empty() && !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(mRef.getSoul()))
{
std::cerr << "Soul '" << mRef.getSoul() << "' not found, removing the soul from soul gem" << std::endl;
mRef.setSoul(std::string());
}
} }
void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const

View file

@ -47,37 +47,45 @@ namespace MWWorld
mPlayer.mData.setPosition(playerPos); mPlayer.mData.setPosition(playerPos);
} }
void Player::saveSkillsAttributes() void Player::saveStats()
{ {
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
for (int i=0; i<ESM::Skill::Length; ++i) for (int i=0; i<ESM::Skill::Length; ++i)
mSaveSkills[i] = stats.getSkill(i); mSaveSkills[i] = stats.getSkill(i);
for (int i=0; i<ESM::Attribute::Length; ++i) for (int i=0; i<ESM::Attribute::Length; ++i)
mSaveAttributes[i] = stats.getAttribute(i); mSaveAttributes[i] = stats.getAttribute(i);
} }
void Player::restoreSkillsAttributes() void Player::restoreStats()
{
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
for (int i=0; i<ESM::Skill::Length; ++i)
stats.setSkill(i, mSaveSkills[i]);
for (int i=0; i<ESM::Attribute::Length; ++i)
stats.setAttribute(i, mSaveAttributes[i]);
}
void Player::setWerewolfSkillsAttributes()
{ {
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
creatureStats.setHealth(int(health.getBase() / gmst.find("fWereWolfHealth")->getFloat()));
for (int i=0; i<ESM::Skill::Length; ++i)
npcStats.setSkill(i, mSaveSkills[i]);
for (int i=0; i<ESM::Attribute::Length; ++i)
npcStats.setAttribute(i, mSaveAttributes[i]);
}
void Player::setWerewolfStats()
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
creatureStats.setHealth(int(health.getBase() * gmst.find("fWereWolfHealth")->getFloat()));
for(size_t i = 0;i < ESM::Attribute::Length;++i) for(size_t i = 0;i < ESM::Attribute::Length;++i)
{ {
// Oh, Bethesda. It's "Intelligence". // Oh, Bethesda. It's "Intelligence".
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
ESM::Attribute::sAttributeNames[i]); ESM::Attribute::sAttributeNames[i]);
MWMechanics::AttributeValue value = stats.getAttribute(i); MWMechanics::AttributeValue value = npcStats.getAttribute(i);
value.setBase(int(gmst.find(name)->getFloat())); value.setBase(int(gmst.find(name)->getFloat()));
stats.setAttribute(i, value); npcStats.setAttribute(i, value);
} }
for(size_t i = 0;i < ESM::Skill::Length;i++) for(size_t i = 0;i < ESM::Skill::Length;i++)
@ -90,9 +98,9 @@ namespace MWWorld
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
ESM::Skill::sSkillNames[i]); ESM::Skill::sSkillNames[i]);
MWMechanics::SkillValue value = stats.getSkill(i); MWMechanics::SkillValue value = npcStats.getSkill(i);
value.setBase(int(gmst.find(name)->getFloat())); value.setBase(int(gmst.find(name)->getFloat()));
stats.setSkill(i, value); npcStats.setSkill(i, value);
} }
} }
@ -366,8 +374,8 @@ namespace MWWorld
if (player.mObject.mNpcStats.mWerewolfDeprecatedData && player.mObject.mNpcStats.mIsWerewolf) if (player.mObject.mNpcStats.mWerewolfDeprecatedData && player.mObject.mNpcStats.mIsWerewolf)
{ {
saveSkillsAttributes(); saveStats();
setWerewolfSkillsAttributes(); setWerewolfStats();
} }
getPlayer().getClass().getCreatureStats(getPlayer()).getAiSequence().clear(); getPlayer().getClass().getCreatureStats(getPlayer()).getAiSequence().clear();

View file

@ -46,7 +46,7 @@ namespace MWWorld
int mCurrentCrimeId; // the id assigned witnesses int mCurrentCrimeId; // the id assigned witnesses
int mPaidCrimeId; // the last id paid off (0 bounty) int mPaidCrimeId; // the last id paid off (0 bounty)
// Saved skills and attributes prior to becoming a werewolf // Saved stats prior to becoming a werewolf
MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length]; MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length];
MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length]; MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length];
@ -56,9 +56,9 @@ namespace MWWorld
Player(const ESM::NPC *player); Player(const ESM::NPC *player);
void saveSkillsAttributes(); void saveStats();
void restoreSkillsAttributes(); void restoreStats();
void setWerewolfSkillsAttributes(); void setWerewolfStats();
// For mark/recall magic effects // For mark/recall magic effects
void markPosition (CellStore* markedCell, const ESM::Position& markedPosition); void markPosition (CellStore* markedCell, const ESM::Position& markedPosition);

View file

@ -79,6 +79,9 @@ namespace
if (ptr.getClass().isActor()) if (ptr.getClass().isActor())
rendering.addWaterRippleEmitter(ptr); rendering.addWaterRippleEmitter(ptr);
// Restore effect particles
MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr);
} }
void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,

View file

@ -592,7 +592,7 @@ namespace MWWorld
const ESM::Cell *ptr = search(id); const ESM::Cell *ptr = search(id);
if (ptr == 0) { if (ptr == 0) {
std::ostringstream msg; std::ostringstream msg;
msg << "Interior cell '" << id << "' not found"; msg << "Cell '" << id << "' not found";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
return ptr; return ptr;

View file

@ -9,7 +9,6 @@
#include <components/fallback/fallback.hpp> #include <components/fallback/fallback.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -103,6 +102,8 @@ Weather::Weather(const std::string& name,
const Fallback::Map& fallback, const Fallback::Map& fallback,
float stormWindSpeed, float stormWindSpeed,
float rainSpeed, float rainSpeed,
float dlFactor,
float dlOffset,
const std::string& particleEffect) const std::string& particleEffect)
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture")) : mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"), , mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
@ -142,6 +143,8 @@ Weather::Weather(const std::string& name,
, mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement")) , mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement"))
, mFlashBrightness(0.0f) , mFlashBrightness(0.0f)
{ {
mDL.FogFactor = dlFactor;
mDL.FogOffset = dlOffset;
mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0"); mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0");
mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1"); mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1");
mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2"); mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2");
@ -520,6 +523,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall
, mSecunda("Secunda", fallback) , mSecunda("Secunda", fallback)
, mWindSpeed(0.f) , mWindSpeed(0.f)
, mIsStorm(false) , mIsStorm(false)
, mPrecipitation(false)
, mStormDirection(0,1,0) , mStormDirection(0,1,0)
, mCurrentRegion() , mCurrentRegion()
, mTimePassed(0) , mTimePassed(0)
@ -541,16 +545,18 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall
mTimeSettings.mSunriseTime = mSunriseTime; mTimeSettings.mSunriseTime = mSunriseTime;
mWeatherSettings.reserve(10); mWeatherSettings.reserve(10);
addWeather("Clear", fallback); // 0 // These distant land fog factor and offset values are the defaults MGE XE provides. Should be
addWeather("Cloudy", fallback); // 1 // provided by settings somewhere?
addWeather("Foggy", fallback); // 2 addWeather("Clear", fallback, 1.0f, 0.0f); // 0
addWeather("Overcast", fallback); // 3 addWeather("Cloudy", fallback, 0.9f, 0.0f); // 1
addWeather("Rain", fallback); // 4 addWeather("Foggy", fallback, 0.2f, 30.0f); // 2
addWeather("Thunderstorm", fallback); // 5 addWeather("Overcast", fallback, 0.7f, 0.0f); // 3
addWeather("Ashstorm", fallback, "meshes\\ashcloud.nif"); // 6 addWeather("Rain", fallback, 0.5f, 10.0f); // 4
addWeather("Blight", fallback, "meshes\\blightcloud.nif"); // 7 addWeather("Thunderstorm", fallback, 0.5f, 20.0f); // 5
addWeather("Snow", fallback, "meshes\\snow.nif"); // 8 addWeather("Ashstorm", fallback, 0.2f, 50.0f, "meshes\\ashcloud.nif"); // 6
addWeather("Blizzard", fallback, "meshes\\blizzard.nif"); // 9 addWeather("Blight", fallback, 0.2f, 60.0f, "meshes\\blightcloud.nif"); // 7
addWeather("Snow", fallback, 0.5f, 40.0f, "meshes\\snow.nif"); // 8
addWeather("Blizzard", fallback, 0.16f, 70.0f, "meshes\\blizzard.nif"); // 9
Store<ESM::Region>::iterator it = store.get<ESM::Region>().begin(); Store<ESM::Region>::iterator it = store.get<ESM::Region>().begin();
for(; it != store.get<ESM::Region>().end(); ++it) for(; it != store.get<ESM::Region>().end(); ++it)
@ -608,14 +614,11 @@ void WeatherManager::modRegion(const std::string& regionID, const std::vector<ch
} }
} }
void WeatherManager::playerTeleported() void WeatherManager::playerTeleported(const std::string& playerRegion, bool isExterior)
{ {
// If the player teleports to an outdoors cell in a new region (for instance, by travelling), the weather needs to // If the player teleports to an outdoors cell in a new region (for instance, by travelling), the weather needs to
// be changed immediately, and any transitions for the previous region discarded. // be changed immediately, and any transitions for the previous region discarded.
MWBase::World* world = MWBase::Environment::get().getWorld();
if(world->isCellExterior() || world->isCellQuasiExterior())
{ {
std::string playerRegion = Misc::StringUtils::lowerCase(world->getPlayerPtr().getCell()->getCell()->mRegion);
std::map<std::string, RegionWeather>::iterator it = mRegions.find(playerRegion); std::map<std::string, RegionWeather>::iterator it = mRegions.find(playerRegion);
if(it != mRegions.end() && playerRegion != mCurrentRegion) if(it != mRegions.end() && playerRegion != mCurrentRegion)
{ {
@ -625,11 +628,9 @@ void WeatherManager::playerTeleported()
} }
} }
void WeatherManager::update(float duration, bool paused) void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior)
{ {
MWWorld::ConstPtr player = MWMechanics::getPlayer(); MWWorld::ConstPtr player = MWMechanics::getPlayer();
MWBase::World& world = *MWBase::Environment::get().getWorld();
TimeStamp time = world.getTimeStamp();
if(!paused || mFastForward) if(!paused || mFastForward)
{ {
@ -647,8 +648,7 @@ void WeatherManager::update(float duration, bool paused)
updateWeatherTransitions(duration); updateWeatherTransitions(duration);
} }
const bool exterior = (world.isCellExterior() || world.isCellQuasiExterior()); if(!isExterior)
if(!exterior)
{ {
mRendering.setSkyEnabled(false); mRendering.setSkyEnabled(false);
stopSounds(); stopSounds();
@ -660,6 +660,10 @@ void WeatherManager::update(float duration, bool paused)
mWindSpeed = mResult.mWindSpeed; mWindSpeed = mResult.mWindSpeed;
mIsStorm = mResult.mIsStorm; mIsStorm = mResult.mIsStorm;
// For some reason Ash Storm is not considered as a precipitation weather in game
mPrecipitation = !(mResult.mParticleEffect.empty() && mResult.mRainEffect.empty())
&& mResult.mParticleEffect != "meshes\\ashcloud.nif";
if (mIsStorm) if (mIsStorm)
{ {
osg::Vec3f playerPos (player.getRefData().getPosition().asVec3()); osg::Vec3f playerPos (player.getRefData().getPosition().asVec3());
@ -720,7 +724,8 @@ void WeatherManager::update(float duration, bool paused)
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time)); mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time)); mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time));
mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor); mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mDLFogFactor,
mResult.mDLFogOffset/100.0f, mResult.mFogColor);
mRendering.setAmbientColour(mResult.mAmbientColor); mRendering.setAmbientColour(mResult.mAmbientColor);
mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView); mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView);
@ -777,12 +782,11 @@ unsigned int WeatherManager::getWeatherID() const
return mCurrentWeather; return mCurrentWeather;
} }
bool WeatherManager::isDark() const bool WeatherManager::useTorches(float hour) const
{ {
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp(); bool isDark = hour < mSunriseTime || hour > mTimeSettings.mNightStart - 1;
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior()); return isDark && !mPrecipitation;
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mTimeSettings.mNightStart - 1);
} }
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress) void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
@ -866,11 +870,12 @@ void WeatherManager::clear()
inline void WeatherManager::addWeather(const std::string& name, inline void WeatherManager::addWeather(const std::string& name,
const Fallback::Map& fallback, const Fallback::Map& fallback,
float dlFactor, float dlOffset,
const std::string& particleEffect) const std::string& particleEffect)
{ {
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat(); static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, particleEffect); Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect);
mWeatherSettings.push_back(weather); mWeatherSettings.push_back(weather);
} }
@ -1058,6 +1063,8 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1); mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings); mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings);
mResult.mDLFogFactor = current.mDL.FogFactor;
mResult.mDLFogOffset = current.mDL.FogOffset;
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings); mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings); mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings); mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
@ -1113,6 +1120,8 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor); mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor);
mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor); mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor);
mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor);
mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor);
mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor);
mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor);
mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor);
mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor);

View file

@ -73,6 +73,8 @@ namespace MWWorld
const Fallback::Map& fallback, const Fallback::Map& fallback,
float stormWindSpeed, float stormWindSpeed,
float rainSpeed, float rainSpeed,
float dlFactor,
float dlOffset,
const std::string& particleEffect); const std::string& particleEffect);
std::string mCloudTexture; std::string mCloudTexture;
@ -102,6 +104,12 @@ namespace MWWorld
// Also appears to modify how visible the sun, moons, and stars are for various weather effects. // Also appears to modify how visible the sun, moons, and stars are for various weather effects.
float mGlareView; float mGlareView;
// Fog factor and offset used with distant land rendering.
struct {
float FogFactor;
float FogOffset;
} mDL;
// Sound effect // Sound effect
// This is used for Blight, Ashstorm and Blizzard (Bloodmoon) // This is used for Blight, Ashstorm and Blizzard (Bloodmoon)
std::string mAmbientLoopSoundID; std::string mAmbientLoopSoundID;
@ -218,14 +226,14 @@ namespace MWWorld
*/ */
void changeWeather(const std::string& regionID, const unsigned int weatherID); void changeWeather(const std::string& regionID, const unsigned int weatherID);
void modRegion(const std::string& regionID, const std::vector<char>& chances); void modRegion(const std::string& regionID, const std::vector<char>& chances);
void playerTeleported(); void playerTeleported(const std::string& playerRegion, bool isExterior);
/** /**
* Per-frame update * Per-frame update
* @param duration * @param duration
* @param paused * @param paused
*/ */
void update(float duration, bool paused = false); void update(float duration, bool paused, const TimeStamp& time, bool isExterior);
void stopSounds(); void stopSounds();
@ -240,8 +248,7 @@ namespace MWWorld
unsigned int getWeatherID() const; unsigned int getWeatherID() const;
/// @see World::isDark bool useTorches(float hour) const;
bool isDark() const;
void write(ESM::ESMWriter& writer, Loading::Listener& progress); void write(ESM::ESMWriter& writer, Loading::Listener& progress);
@ -275,6 +282,7 @@ namespace MWWorld
float mWindSpeed; float mWindSpeed;
bool mIsStorm; bool mIsStorm;
bool mPrecipitation;
osg::Vec3f mStormDirection; osg::Vec3f mStormDirection;
std::string mCurrentRegion; std::string mCurrentRegion;
@ -293,6 +301,7 @@ namespace MWWorld
void addWeather(const std::string& name, void addWeather(const std::string& name,
const Fallback::Map& fallback, const Fallback::Map& fallback,
float dlFactor, float dlOffset,
const std::string& particleEffect = ""); const std::string& particleEffect = "");
void importRegions(); void importRegions();

View file

@ -2244,6 +2244,8 @@ namespace MWWorld
model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS()); model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS());
mPhysics->remove(getPlayerPtr()); mPhysics->remove(getPlayerPtr());
mPhysics->addActor(getPlayerPtr(), model); mPhysics->addActor(getPlayerPtr(), model);
applyLoopingParticles(player);
} }
int World::canRest () int World::canRest ()
@ -2831,6 +2833,19 @@ namespace MWWorld
mProjectileManager->launchMagicBolt(spellId, caster, fallbackDirection); mProjectileManager->launchMagicBolt(spellId, caster, fallbackDirection);
} }
void World::applyLoopingParticles(const MWWorld::Ptr& ptr)
{
const MWWorld::Class &cls = ptr.getClass();
if (cls.isActor())
{
MWMechanics::ApplyLoopingParticlesVisitor visitor(ptr);
cls.getCreatureStats(ptr).getActiveSpells().visitEffectSources(visitor);
cls.getCreatureStats(ptr).getSpells().visitEffectSources(visitor);
if (cls.hasInventoryStore(ptr))
cls.getInventoryStore(ptr).visitEffectSources(visitor);
}
}
const std::vector<std::string>& World::getContentFiles() const const std::vector<std::string>& World::getContentFiles() const
{ {
return mContentFiles; return mContentFiles;
@ -2847,11 +2862,17 @@ namespace MWWorld
MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(actor); MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(actor);
} }
bool World::isDark() const bool World::useTorches() const
{ {
// If we are in exterior, check the weather manager.
// In interiors there are no precipitations and sun, so check the ambient
// Looks like pseudo-exteriors considered as interiors in this case
MWWorld::CellStore* cell = mPlayer->getPlayer().getCell(); MWWorld::CellStore* cell = mPlayer->getPlayer().getCell();
if (cell->isExterior()) if (cell->isExterior())
return mWeatherManager->isDark(); {
float hour = getTimeStamp().getHour();
return mWeatherManager->useTorches(hour);
}
else else
{ {
uint32_t ambient = cell->getCell()->mAmbi.mAmbient; uint32_t ambient = cell->getCell()->mAmbi.mAmbient;
@ -3012,13 +3033,17 @@ namespace MWWorld
void World::updateWeather(float duration, bool paused) void World::updateWeather(float duration, bool paused)
{ {
bool isExterior = isCellExterior() || isCellQuasiExterior();
if (mPlayer->wasTeleported()) if (mPlayer->wasTeleported())
{ {
mPlayer->setTeleported(false); mPlayer->setTeleported(false);
mWeatherManager->playerTeleported();
const std::string playerRegion = Misc::StringUtils::lowerCase(getPlayerPtr().getCell()->getCell()->mRegion);
mWeatherManager->playerTeleported(playerRegion, isExterior);
} }
mWeatherManager->update(duration, paused); const TimeStamp time = getTimeStamp();
mWeatherManager->update(duration, paused, time, isExterior);
} }
struct AddDetectedReferenceVisitor struct AddDetectedReferenceVisitor

View file

@ -604,12 +604,13 @@ namespace MWWorld
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override; const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override;
void applyLoopingParticles(const MWWorld::Ptr& ptr);
const std::vector<std::string>& getContentFiles() const override; const std::vector<std::string>& getContentFiles() const override;
void breakInvisibility (const MWWorld::Ptr& actor) override; void breakInvisibility (const MWWorld::Ptr& actor) override;
// Are we in an exterior or pseudo-exterior cell and it's night?
bool isDark() const override; // Allow NPCs to use torches?
bool useTorches() const override;
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override; bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;

View file

@ -1,7 +1,7 @@
find_package(GTest REQUIRED) find_package(GTest REQUIRED)
if (GTEST_FOUND) if (GTEST_FOUND)
include_directories(${GTEST_INCLUDE_DIRS}) include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
file(GLOB UNITTEST_SRC_FILES file(GLOB UNITTEST_SRC_FILES
../openmw/mwworld/store.cpp ../openmw/mwworld/store.cpp

View file

@ -62,10 +62,11 @@ Wizard::MainWizard::MainWizard(QWidget *parent) :
setupInstallations(); setupInstallations();
setupPages(); setupPages();
const boost::filesystem::path& installedPath = mCfgMgr.getInstallPath(); const boost::filesystem::path& installationPath = mCfgMgr.getInstallPath();
if (!installedPath.empty()) if (!installationPath.empty())
{ {
addInstallation(toQString(installedPath)); const boost::filesystem::path& dataPath = installationPath / "Data Files";
addInstallation(toQString(dataPath));
} }
} }

View file

@ -1,7 +1,7 @@
#------------------------------------------------------------------- #-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE # This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine) # (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/ # For the latest info, see https://www.ogre3d.org/
# #
# The contents of this file are placed in the public domain. Feel # The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like. # free to make use of it in any way you like.

View file

@ -4,7 +4,7 @@
# LIBUNSHIELD_FOUND, if false, do not try to link to LibUnshield # LIBUNSHIELD_FOUND, if false, do not try to link to LibUnshield
# LIBUNSHIELD_INCLUDE_DIRS, where to find the headers # LIBUNSHIELD_INCLUDE_DIRS, where to find the headers
# #
# Created by Tom Mason (wheybags) for OpenMW (http://openmw.org), based on FindMPG123.cmake # Created by Tom Mason (wheybags) for OpenMW (https://openmw.org), based on FindMPG123.cmake
# #
# Ripped off from other sources. In fact, this file is so generic (I # Ripped off from other sources. In fact, this file is so generic (I
# just did a search and replace on another file) that I wonder why the # just did a search and replace on another file) that I wonder why the

View file

@ -1,94 +0,0 @@
#-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
# - Try to find OpenGLES
# Once done this will define
#
# OPENGLES_FOUND - system has OpenGLES
# OPENGLES_INCLUDE_DIR - the GL include directory
# OPENGLES_LIBRARIES - Link these to use OpenGLES
IF (WIN32)
IF (CYGWIN)
FIND_PATH(OPENGLES_INCLUDE_DIR GLES/gl.h )
FIND_LIBRARY(OPENGLES_gl_LIBRARY libgles_cm )
ELSE (CYGWIN)
IF(BORLAND)
SET (OPENGLES_gl_LIBRARY import32 CACHE STRING "OpenGL ES 1.x library for win32")
ELSE(BORLAND)
#MS compiler - todo - fix the following line:
SET (OPENGLES_gl_LIBRARY ${OGRE_SOURCE_DIR}/Dependencies/lib/release/libgles_cm.lib CACHE STRING "OpenGL ES 1.x library for win32")
ENDIF(BORLAND)
ENDIF (CYGWIN)
ELSE (WIN32)
IF (APPLE)
#create_search_paths(/Developer/Platforms)
#findpkg_framework(OpenGLES)
#set(OPENGLES_gl_LIBRARY "-framework OpenGLES")
ELSE(APPLE)
FIND_PATH(OPENGLES_INCLUDE_DIR GLES/gl.h
/opt/vc/include
/opt/graphics/OpenGL/include
/usr/openwin/share/include
/usr/X11R6/include
/usr/include
)
FIND_LIBRARY(OPENGLES_gl_LIBRARY
NAMES GLES_CM GLESv1_CM
PATHS /opt/vc/lib
/opt/graphics/OpenGL/lib
/usr/openwin/lib
/usr/shlib /usr/X11R6/lib
/usr/lib
)
# On Unix OpenGL most certainly always requires X11.
# Feel free to tighten up these conditions if you don't
# think this is always true.
#IF (OPENGLES_gl_LIBRARY)
# IF(NOT X11_FOUND)
# INCLUDE(FindX11)
# ENDIF(NOT X11_FOUND)
# IF (X11_FOUND)
# SET (OPENGLES_LIBRARIES ${X11_LIBRARIES})
# ENDIF (X11_FOUND)
#ENDIF (OPENGLES_gl_LIBRARY)
ENDIF(APPLE)
ENDIF (WIN32)
SET( OPENGLES_FOUND "NO" )
IF(OPENGLES_gl_LIBRARY)
SET( OPENGLES_LIBRARIES ${OPENGLES_gl_LIBRARY} ${OPENGLES_LIBRARIES})
SET( OPENGLES_FOUND "YES" )
ENDIF(OPENGLES_gl_LIBRARY)
MARK_AS_ADVANCED(
OPENGLES_INCLUDE_DIR
OPENGLES_gl_LIBRARY
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENGLES REQUIRED_VARS OPENGLES_LIBRARIES OPENGLES_INCLUDE_DIR)

View file

@ -26,12 +26,6 @@ else (GIT_CHECKOUT)
configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE}) configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE})
endif (GIT_CHECKOUT) endif (GIT_CHECKOUT)
if (OPENGL_ES)
find_package(OpenGLES REQUIRED)
else()
find_package(OpenGL REQUIRED)
endif()
# source files # source files
add_component_dir (settings add_component_dir (settings
@ -191,12 +185,6 @@ include_directories(${Bullet_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR})
if (OPENGL_ES)
set(GL_LIB ${OPENGLES_gl_LIBRARY})
else()
set(GL_LIB ${OPENGL_gl_LIBRARY})
endif()
target_link_libraries(components target_link_libraries(components
${Boost_SYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}
${Boost_FILESYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY}
@ -213,8 +201,7 @@ target_link_libraries(components
${OSGANIMATION_LIBRARIES} ${OSGANIMATION_LIBRARIES}
${Bullet_LIBRARIES} ${Bullet_LIBRARIES}
${SDL2_LIBRARIES} ${SDL2_LIBRARIES}
# For MyGUI platform ${OPENGL_gl_LIBRARY}
${GL_LIB}
${MyGUI_LIBRARIES} ${MyGUI_LIBRARIES}
) )

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (bsa_file.cpp) is part of the OpenMW package. This file (bsa_file.cpp) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (bsa_file.h) is part of the OpenMW package. This file (bsa_file.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -493,8 +493,10 @@ bool Config::GameSettings::hasMaster()
{ {
bool result = false; bool result = false;
QStringList content = mSettings.values(QString(Config::GameSettings::sContentKey)); QStringList content = mSettings.values(QString(Config::GameSettings::sContentKey));
for (int i = 0; i < content.count(); ++i) { for (int i = 0; i < content.count(); ++i)
if (content.at(i).contains(".omwgame") || content.at(i).contains(".esm")) { {
if (content.at(i).endsWith(QLatin1String(".omwgame"), Qt::CaseInsensitive) || content.at(i).endsWith(QLatin1String(".esm"), Qt::CaseInsensitive))
{
result = true; result = true;
break; break;
} }

View file

@ -1,5 +1,7 @@
#include "fallback.hpp" #include "fallback.hpp"
#include <iostream>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
@ -17,6 +19,7 @@ namespace Fallback
std::map<std::string,std::string>::const_iterator it; std::map<std::string,std::string>::const_iterator it;
if((it = mFallbackMap.find(fall)) == mFallbackMap.end()) if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
{ {
std::cerr << "Warning: fallback value " << fall << " not found." << std::endl;
return ""; return "";
} }
return it->second; return it->second;
@ -25,7 +28,7 @@ namespace Fallback
float Map::getFallbackFloat(const std::string& fall) const float Map::getFallbackFloat(const std::string& fall) const
{ {
std::string fallback=getFallbackString(fall); std::string fallback=getFallbackString(fall);
if(fallback.empty()) if (fallback.empty())
return 0; return 0;
else else
return boost::lexical_cast<float>(fallback); return boost::lexical_cast<float>(fallback);
@ -34,7 +37,7 @@ namespace Fallback
int Map::getFallbackInt(const std::string& fall) const int Map::getFallbackInt(const std::string& fall) const
{ {
std::string fallback=getFallbackString(fall); std::string fallback=getFallbackString(fall);
if(fallback.empty()) if (fallback.empty())
return 0; return 0;
else else
return std::stoi(fallback); return std::stoi(fallback);
@ -43,7 +46,7 @@ namespace Fallback
bool Map::getFallbackBool(const std::string& fall) const bool Map::getFallbackBool(const std::string& fall) const
{ {
std::string fallback=getFallbackString(fall); std::string fallback=getFallbackString(fall);
if(fallback.empty()) if (fallback.empty())
return false; return false;
else else
return stob(fallback); return stob(fallback);
@ -52,8 +55,8 @@ namespace Fallback
osg::Vec4f Map::getFallbackColour(const std::string& fall) const osg::Vec4f Map::getFallbackColour(const std::string& fall) const
{ {
std::string sum=getFallbackString(fall); std::string sum=getFallbackString(fall);
if(sum.empty()) if (sum.empty())
return osg::Vec4f(0.f,0.f,0.f,1.f); return osg::Vec4f(0.5f,0.5f,0.5f,1.f);
else else
{ {
std::string ret[3]; std::string ret[3];

View file

@ -339,52 +339,76 @@ namespace Gui
+ MyGUI::utility::toString((fontSize-data[i].ascent))); + MyGUI::utility::toString((fontSize-data[i].ascent)));
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height))); code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
// More hacks! The french game uses several win1252 characters that are not included // Fall back from unavailable Windows-1252 encoding symbols to similar characters available in the game fonts
// in the cp437 encoding of the font. Fall back to similar available characters. std::multimap<int, int> additional; // fallback glyph index, unicode
if (mEncoding == ToUTF8::CP437) additional.insert(std::make_pair(156, 0x00A2)); // cent sign
additional.insert(std::make_pair(89, 0x00A5)); // yen sign
additional.insert(std::make_pair(221, 0x00A6)); // broken bar
additional.insert(std::make_pair(99, 0x00A9)); // copyright sign
additional.insert(std::make_pair(97, 0x00AA)); // prima ordinal indicator
additional.insert(std::make_pair(60, 0x00AB)); // double left-pointing angle quotation mark
additional.insert(std::make_pair(45, 0x00AD)); // soft hyphen
additional.insert(std::make_pair(114, 0x00AE)); // registered trademark symbol
additional.insert(std::make_pair(45, 0x00AF)); // macron
additional.insert(std::make_pair(241, 0x00B1)); // plus-minus sign
additional.insert(std::make_pair(50, 0x00B2)); // superscript two
additional.insert(std::make_pair(51, 0x00B3)); // superscript three
additional.insert(std::make_pair(44, 0x00B8)); // cedilla
additional.insert(std::make_pair(49, 0x00B9)); // superscript one
additional.insert(std::make_pair(111, 0x00BA)); // primo ordinal indicator
additional.insert(std::make_pair(62, 0x00BB)); // double right-pointing angle quotation mark
additional.insert(std::make_pair(63, 0x00BF)); // inverted question mark
additional.insert(std::make_pair(65, 0x00C6)); // latin capital ae ligature
additional.insert(std::make_pair(79, 0x00D8)); // latin capital o with stroke
additional.insert(std::make_pair(97, 0x00E6)); // latin small ae ligature
additional.insert(std::make_pair(111, 0x00F8)); // latin small o with stroke
additional.insert(std::make_pair(79, 0x0152)); // latin capital oe ligature
additional.insert(std::make_pair(111, 0x0153)); // latin small oe ligature
additional.insert(std::make_pair(83, 0x015A)); // latin capital s with caron
additional.insert(std::make_pair(115, 0x015B)); // latin small s with caron
additional.insert(std::make_pair(89, 0x0178)); // latin capital y with diaresis
additional.insert(std::make_pair(90, 0x017D)); // latin capital z with caron
additional.insert(std::make_pair(122, 0x017E)); // latin small z with caron
additional.insert(std::make_pair(102, 0x0192)); // latin small f with hook
additional.insert(std::make_pair(94, 0x02C6)); // circumflex modifier
additional.insert(std::make_pair(126, 0x02DC)); // small tilde
additional.insert(std::make_pair(69, 0x0401)); // cyrillic capital io (no diaeresis latin e is available)
additional.insert(std::make_pair(137, 0x0451)); // cyrillic small io
additional.insert(std::make_pair(45, 0x2012)); // figure dash
additional.insert(std::make_pair(45, 0x2013)); // en dash
additional.insert(std::make_pair(45, 0x2014)); // em dash
additional.insert(std::make_pair(39, 0x2018)); // left single quotation mark
additional.insert(std::make_pair(39, 0x2019)); // right single quotation mark
additional.insert(std::make_pair(44, 0x201A)); // single low quotation mark
additional.insert(std::make_pair(39, 0x201B)); // single high quotation mark (reversed)
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark
additional.insert(std::make_pair(44, 0x201E)); // double low quotation mark
additional.insert(std::make_pair(34, 0x201F)); // double high quotation mark (reversed)
additional.insert(std::make_pair(43, 0x2020)); // dagger
additional.insert(std::make_pair(216, 0x2021)); // double dagger (note: this glyph is not available)
additional.insert(std::make_pair(46, 0x2026)); // ellipsis
additional.insert(std::make_pair(37, 0x2030)); // per mille sign
additional.insert(std::make_pair(60, 0x2039)); // single left-pointing angle quotation mark
additional.insert(std::make_pair(62, 0x203A)); // single right-pointing angle quotation mark
additional.insert(std::make_pair(101, 0x20AC)); // euro sign
additional.insert(std::make_pair(84, 0x2122)); // trademark sign
additional.insert(std::make_pair(45, 0x2212)); // minus sign
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
{ {
std::multimap<int, int> additional; // <cp437, unicode> if (it->first != i)
additional.insert(std::make_pair(39, 0x2019)); // apostrophe continue;
additional.insert(std::make_pair(45, 0x2013)); // dash code = codes->createChild("Code");
additional.insert(std::make_pair(45, 0x2014)); // dash code->addAttribute("index", it->second);
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark + MyGUI::utility::toString(y1) + " "
additional.insert(std::make_pair(44, 0x201A)); + MyGUI::utility::toString(w) + " "
additional.insert(std::make_pair(44, 0x201E)); + MyGUI::utility::toString(h));
additional.insert(std::make_pair(43, 0x2020)); code->addAttribute("advance", data[i].width);
additional.insert(std::make_pair(94, 0x02C6)); code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
additional.insert(std::make_pair(37, 0x2030)); + MyGUI::utility::toString((fontSize-data[i].ascent)));
additional.insert(std::make_pair(83, 0x0160)); code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
additional.insert(std::make_pair(60, 0x2039));
additional.insert(std::make_pair(79, 0x0152));
additional.insert(std::make_pair(90, 0x017D));
additional.insert(std::make_pair(39, 0x2019));
additional.insert(std::make_pair(126, 0x02DC));
additional.insert(std::make_pair(84, 0x2122));
additional.insert(std::make_pair(83, 0x0161));
additional.insert(std::make_pair(62, 0x203A));
additional.insert(std::make_pair(111, 0x0153));
additional.insert(std::make_pair(122, 0x017E));
additional.insert(std::make_pair(89, 0x0178));
additional.insert(std::make_pair(156, 0x00A2));
additional.insert(std::make_pair(46, 0x2026));
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
{
if (it->first != i)
continue;
code = codes->createChild("Code");
code->addAttribute("index", it->second);
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
+ MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " "
+ MyGUI::utility::toString(h));
code->addAttribute("advance", data[i].width);
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
}
} }
// ASCII vertical bar, use this as text input cursor // ASCII vertical bar, use this as text input cursor

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (controlled.h) is part of the OpenMW package. This file (controlled.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (controller.h) is part of the OpenMW package. This file (controller.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (data.h) is part of the OpenMW package. This file (data.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (effect.h) is part of the OpenMW package. This file (effect.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (extra.h) is part of the OpenMW package. This file (extra.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (nif_types.h) is part of the OpenMW package. This file (nif_types.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (property.h) is part of the OpenMW package. This file (property.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -2,7 +2,7 @@
OpenMW - The completely unofficial reimplementation of Morrowind OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com > Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/ WWW: https://openmw.org/
This file (record.h) is part of the OpenMW package. This file (record.h) is part of the OpenMW package.
@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see version 3 along with this program. If not, see
http://www.gnu.org/licenses/ . https://www.gnu.org/licenses/ .
*/ */

View file

@ -25,6 +25,8 @@ namespace SceneUtil
class ControllerFunction class ControllerFunction
{ {
public: public:
virtual ~ControllerFunction() = default;
virtual float calculate(float input) const = 0; virtual float calculate(float input) const = 0;
/// Get the "stop time" of the controller function, typically the maximum of the calculate() function. /// Get the "stop time" of the controller function, typically the maximum of the calculate() function.

View file

@ -91,7 +91,7 @@ void GraphicsWindowSDL2::init()
SDL_Window *oldWin = SDL_GL_GetCurrentWindow(); SDL_Window *oldWin = SDL_GL_GetCurrentWindow();
SDL_GLContext oldCtx = SDL_GL_GetCurrentContext(); SDL_GLContext oldCtx = SDL_GL_GetCurrentContext();
#if defined(OPENGL_ES) || defined(ANDROID) #if defined(ANDROID)
int major = 1; int major = 1;
int minor = 1; int minor = 1;
char *ver = getenv("OPENMW_GLES_VERSION"); char *ver = getenv("OPENMW_GLES_VERSION");

View file

@ -292,7 +292,7 @@ public:
ostream << "# to its default, simply remove it from this file. For available" << std::endl; ostream << "# to its default, simply remove it from this file. For available" << std::endl;
ostream << "# settings, see the file 'settings-default.cfg' or the documentation at:" << std::endl; ostream << "# settings, see the file 'settings-default.cfg' or the documentation at:" << std::endl;
ostream << "#" << std::endl; ostream << "#" << std::endl;
ostream << "# http://openmw.readthedocs.io/en/master/reference/modding/settings/index.html" << std::endl; ostream << "# https://openmw.readthedocs.io/en/master/reference/modding/settings/index.html" << std::endl;
} }
// We still have one more thing to do before we're completely done writing the file. // We still have one more thing to do before we're completely done writing the file.

View file

@ -5,13 +5,20 @@
namespace Gui namespace Gui
{ {
bool ImageButton::sDefaultNeedKeyFocus = true;
ImageButton::ImageButton() ImageButton::ImageButton()
: Base() : Base()
, mMouseFocus(false) , mMouseFocus(false)
, mMousePress(false) , mMousePress(false)
, mKeyFocus(false) , mKeyFocus(false)
{ {
setNeedKeyFocus(true); setNeedKeyFocus(sDefaultNeedKeyFocus);
}
void ImageButton::setDefaultNeedKeyFocus(bool enabled)
{
sDefaultNeedKeyFocus = enabled;
} }
void ImageButton::setPropertyOverride(const std::string &_key, const std::string &_value) void ImageButton::setPropertyOverride(const std::string &_key, const std::string &_value)

View file

@ -18,12 +18,16 @@ namespace Gui
ImageButton(); ImageButton();
static void setDefaultNeedKeyFocus(bool enabled);
/// Set mImageNormal, mImageHighlighted and mImagePushed based on file convention (image_idle.ext, image_over.ext and image_pressed.ext) /// Set mImageNormal, mImageHighlighted and mImagePushed based on file convention (image_idle.ext, image_over.ext and image_pressed.ext)
void setImage(const std::string& image); void setImage(const std::string& image);
private: private:
void updateImage(); void updateImage();
static bool sDefaultNeedKeyFocus;
protected: protected:
virtual void setPropertyOverride(const std::string& _key, const std::string& _value); virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
virtual void onMouseLostFocus(MyGUI::Widget* _new); virtual void onMouseLostFocus(MyGUI::Widget* _new);

View file

@ -20,7 +20,7 @@
# This tag specifies the encoding used for all characters in the config file # This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text # that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # built into libc) for the transcoding. See https://www.gnu.org/software/libiconv
# for the list of possible encodings. # for the list of possible encodings.
# The default value is: UTF-8. # The default value is: UTF-8.
@ -295,7 +295,7 @@ EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable # according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details. # documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can # The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues. # case of backward compatibilities issues.
@ -328,7 +328,7 @@ BUILTIN_STL_SUPPORT = YES
CPP_CLI_SUPPORT = NO CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # https://riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead # will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present. # of private inheritance when no explicit protection keyword is present.
# The default value is: NO. # The default value is: NO.
@ -687,7 +687,7 @@ LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib # the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool # extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using # For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. Do not use file names with spaces, bibtex cannot handle them. See # search path. Do not use file names with spaces, bibtex cannot handle them. See
@ -772,7 +772,7 @@ INPUT = @OpenMW_SOURCE_DIR@/apps \
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: http://www.gnu.org/software/libiconv) for the list of # documentation (see: https://www.gnu.org/software/libiconv) for the list of
# possible encodings. # possible encodings.
# The default value is: UTF-8. # The default value is: UTF-8.
@ -993,7 +993,7 @@ SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will # If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in # point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system # source browser. The htags tool is part of GNU's global source tagging system
# (see http://www.gnu.org/software/global/global.html). You will need version # (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher. # 4.8.6 or higher.
# #
# To use it do the following: # To use it do the following:
@ -1136,7 +1136,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the stylesheet and background images according to # will adjust the colors in the stylesheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see # this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value # https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again. # purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220. # Minimum value: 0, maximum value: 359, default value: 220.
@ -1194,7 +1194,7 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be # If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development # generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: http://developer.apple.com/tools/xcode/), introduced with # environment (see: https://developer.apple.com/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in # Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in # that directory and running make install will install the docset in
@ -1239,7 +1239,7 @@ DOCSET_PUBLISHER_NAME = OpenMW
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows. # Windows.
# #
# The HTML Help Workshop contains a compiler that can convert all HTML output # The HTML Help Workshop contains a compiler that can convert all HTML output
@ -1315,7 +1315,7 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace # Project output. For more information please see Qt Help Project / Namespace
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project. # The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
@ -1323,8 +1323,7 @@ QHP_NAMESPACE = org.openmw
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual # Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# folders).
# The default value is: doc. # The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
@ -1332,23 +1331,21 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom # filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom # custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS = QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see: # project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES. # This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS =
@ -1453,7 +1450,7 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering # https://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using prerendered bitmaps. Use this if you do not have LaTeX # instead of using prerendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When # installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path # enabled you may also need to install MathJax separately and configure the path
@ -1465,7 +1462,7 @@ USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for # When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see: # the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details. # https://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best # Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG. # compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS. # The default value is: HTML-CSS.
@ -1480,11 +1477,11 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing # Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of # MathJax. However, it is strongly recommended to install a local copy of
# MathJax from http://www.mathjax.org before deployment. # MathJax from https://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest. # The default value is: https://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example # extension names that should be enabled during MathJax rendering. For example
@ -1495,7 +1492,7 @@ MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site # of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # (see: https://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation. # example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
@ -1542,7 +1539,7 @@ SERVER_BASED_SEARCH = NO
# #
# Doxygen ships with an example indexer ( doxyindexer) and search engine # Doxygen ships with an example indexer ( doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). # Xapian (see: https://xapian.org/).
# #
# See the section "External Indexing and Searching" for details. # See the section "External Indexing and Searching" for details.
# The default value is: NO. # The default value is: NO.
@ -1555,7 +1552,7 @@ EXTERNAL_SEARCH = NO
# #
# Doxygen ships with an example indexer ( doxyindexer) and search engine # Doxygen ships with an example indexer ( doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and # Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details. # Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES. # This tag requires that the tag SEARCHENGINE is set to YES.
@ -1726,7 +1723,7 @@ LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See # bibliography, e.g. plainnat, or ieeetr. See
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. # https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain. # The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1882,7 +1879,7 @@ DOCBOOK_OUTPUT = docbook
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen # If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
# Definitions (see http://autogen.sf.net) file that captures the structure of # Definitions (see http://autogen.sourceforge.net) file that captures the structure of
# the code including all documentation. Note that this feature is still # the code including all documentation. Note that this feature is still
# experimental and incomplete at the moment. # experimental and incomplete at the moment.
# The default value is: NO. # The default value is: NO.
@ -2093,7 +2090,7 @@ HIDE_UNDOC_RELATIONS = NO
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see: # available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is # Bell Labs. The other options in this section have no effect if this option is
# set to NO # set to NO
# The default value is: YES. # The default value is: YES.

View file

@ -18,7 +18,7 @@
# that follow. The default is UTF-8 which is also the encoding used for all # that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the # text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See # iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings. # https://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
@ -581,7 +581,7 @@ INPUT = @OpenMW_SOURCE_DIR@/apps \
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
# also the default input encoding. Doxygen uses libiconv (or the iconv built # also the default input encoding. Doxygen uses libiconv (or the iconv built
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # into libc) for the transcoding. See https://www.gnu.org/software/libiconv for
# the list of possible encodings. # the list of possible encodings.
INPUT_ENCODING = UTF-8 INPUT_ENCODING = UTF-8
@ -753,7 +753,7 @@ REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code # If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen # will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source # built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You # tagging system (see https://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher. # will need version 4.8.6 or higher.
USE_HTAGS = NO USE_HTAGS = NO
@ -928,30 +928,30 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating # The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see # Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace
QHP_NAMESPACE = QHP_NAMESPACE =
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see # Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
# For more information please see # For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. # <a href="https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS = QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
# filter section matches. # filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. # <a href="https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS =

View file

@ -60,16 +60,32 @@ copyright = u'2017, OpenMW Team'
# The short X.Y version. # The short X.Y version.
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version = "UNRELEASED"
def get_openmw_version(haystack):
needle = 'OPENMW_VERSION_MAJOR'
line_counter = 0
for hay in haystack:
if needle in str(hay):
break
line_counter += 1
version = '.'.join([haystack[line_counter][1][1].contents,
haystack[line_counter+1][1][1].contents,
haystack[line_counter+2][1][1].contents])
return version
try: try:
from parse_cmake import parsing from parse_cmake import parsing
cmake_raw = open(project_root+'/CMakeLists.txt', 'r').read() cmake_raw = open(project_root+'/CMakeLists.txt', 'r').read()
cmake_data = parsing.parse(cmake_raw) cmake_data = parsing.parse(cmake_raw)
release = version = '.'.join([cmake_data[24][1][1].contents, release = version = get_openmw_version(cmake_data)
cmake_data[25][1][1].contents,
cmake_data[26][1][1].contents]) except Exception as ex:
except ImportError: print("WARNING: Version will be set to '{0}' because: '{1}'.".format(release, str(ex)))
release = "UNRELEASED" import traceback; traceback.print_exc()
print("WARNING: Unable to import parse_cmake, version will be set to: {0}.".format(release))
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View file

@ -219,6 +219,6 @@ files for textures.
.. Hyperlink targets for the entire document .. Hyperlink targets for the entire document
.. _FFmpeg: http://ffmpeg.org .. _FFmpeg: https://ffmpeg.org
.. _Vorbis: http://www.vorbis.com .. _Vorbis: http://www.vorbis.com
.. _Theora: http://www.theora.org .. _Theora: https://www.theora.org

View file

@ -297,7 +297,7 @@ Placing in plain sight
===================== =====================
Let's hide the Ring of Night vision in the cabin of the [Ancient Shipwreck] Let's hide the Ring of Night vision in the cabin of the [Ancient Shipwreck]
(http://en.uesp.net/wiki/Morrowind:Ancient_Shipwreck), a derelict vessel (https://en.uesp.net/wiki/Morrowind:Ancient_Shipwreck), a derelict vessel
southeast of Dagon Fel. Open the list of Cells (*World**Cells*) and find southeast of Dagon Fel. Open the list of Cells (*World**Cells*) and find
"Ancient Shipwreck, Cabin". "Ancient Shipwreck, Cabin".

View file

@ -185,18 +185,18 @@ The sacks included in Apel's `Various Things - Sacks`_ come in two versions
Since these models have one or two textures applied to them, the fix was not that time-consuming. It gets worse when you have to fix a model that uses loads of textures. The principle is the same, it just requires more manual work which is annoying and takes time. Since these models have one or two textures applied to them, the fix was not that time-consuming. It gets worse when you have to fix a model that uses loads of textures. The principle is the same, it just requires more manual work which is annoying and takes time.
.. _`Netch Bump mapped`: http://www.nexusmods.com/morrowind/mods/42851/? .. _`Netch Bump mapped`: https://www.nexusmods.com/morrowind/mods/42851/?
.. _`Hlaalu Bump mapped`: http://www.nexusmods.com/morrowind/mods/42396/? .. _`Hlaalu Bump mapped`: https://www.nexusmods.com/morrowind/mods/42396/?
.. _`On the Rocks`: http://mw.modhistory.com/download-44-14107 .. _`On the Rocks`: http://mw.modhistory.com/download-44-14107
.. _`texture modding`: https://wiki.openmw.org/index.php?title=TextureModding .. _`texture modding`: https://wiki.openmw.org/index.php?title=TextureModding
.. _`MGE XE`: http://www.nexusmods.com/morrowind/mods/26348/? .. _`MGE XE`: https://www.nexusmods.com/morrowind/mods/26348/?
.. _PeterBitt: http://www.nexusmods.com/morrowind/users/4381248/? .. _PeterBitt: https://www.nexusmods.com/morrowind/users/4381248/?
.. _`PBR Scamp Replacer`: http://www.nexusmods.com/morrowind/mods/44314/? .. _`PBR Scamp Replacer`: https://www.nexusmods.com/morrowind/mods/44314/?
.. _settings.cfg: https://wiki.openmw.org/index.php?title=Settings .. _settings.cfg: https://wiki.openmw.org/index.php?title=Settings
.. _`Multiple data folders`: https://wiki.openmw.org/index.php?title=Mod_installation .. _`Multiple data folders`: https://wiki.openmw.org/index.php?title=Mod_installation
.. _`Various Things - Sacks`: http://www.nexusmods.com/morrowind/mods/42558/? .. _`Various Things - Sacks`: https://www.nexusmods.com/morrowind/mods/42558/?
.. _Lead: http://imgur.com/bwpcYlc .. _Lead: https://imgur.com/bwpcYlc
.. _NifSkope: http://niftools.sourceforge.net/wiki/NifSkope .. _NifSkope: http://niftools.sourceforge.net/wiki/NifSkope
.. _Blocks: http://imgur.com/VmQC0WG .. _Blocks: https://imgur.com/VmQC0WG
.. _`no longer have shiny models`: http://imgur.com/vu1k7n1 .. _`no longer have shiny models`: https://imgur.com/vu1k7n1
.. _`we are done`: http://imgur.com/yyZxlTw .. _`we are done`: https://imgur.com/yyZxlTw

View file

@ -15,7 +15,7 @@ Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts. Th
- To replace the primary "Magic Cards" font: - To replace the primary "Magic Cards" font:
#. Download `Pelagiad <http://isaskar.github.io/Pelagiad/>`_ by Isak Larborn (aka Isaskar). #. Download `Pelagiad <https://isaskar.github.io/Pelagiad/>`_ by Isak Larborn (aka Isaskar).
#. Install the ``openmw_font.xml`` file into ``resources/mygui/openmw_font.xml`` in your OpenMW installation. #. Install the ``openmw_font.xml`` file into ``resources/mygui/openmw_font.xml`` in your OpenMW installation.
#. Copy ``Pelagiad.ttf`` into ``resources/mygui/`` as well. #. Copy ``Pelagiad.ttf`` into ``resources/mygui/`` as well.
#. If desired, you can now delete the original ``Magic_Cards.*`` files from your Data Files/Fonts directory. #. If desired, you can now delete the original ``Magic_Cards.*`` files from your Data Files/Fonts directory.

View file

@ -9,11 +9,7 @@ scaling factor
:Default: 1.0 :Default: 1.0
This setting scales the GUI interface windows. This setting scales the GUI interface windows.
The value must be greater than 0.0. A value of 1.0 results in the normal scale. A value of 1.0 results in the normal scale. Larger values are useful to increase the scale of the GUI for high resolution displays.
Values much larger than 2.0 may result in user interface components being inaccessible.
Until a gamepad interface is created,
increasing this setting is helpful for simulating the larger interface used in console games.
This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
menu transparency menu transparency
@ -24,7 +20,6 @@ menu transparency
:Default: 0.84 :Default: 0.84
This setting controls the transparency of the GUI windows. This setting controls the transparency of the GUI windows.
The value should be between 0.0 (transparent) and 1.0 (opaque).
This setting can be adjusted in game with the Menu Transparency slider in the Prefs panel of the Options menu. This setting can be adjusted in game with the Menu Transparency slider in the Prefs panel of the Options menu.
tooltip delay tooltip delay
@ -36,7 +31,6 @@ tooltip delay
This value determines the number of seconds between when you begin hovering over an item and when its tooltip appears. This value determines the number of seconds between when you begin hovering over an item and when its tooltip appears.
This setting only affects the tooltip delay for objects under the crosshair in GUI mode windows. This setting only affects the tooltip delay for objects under the crosshair in GUI mode windows.
There does not appear to be a setting to control the tool tip delay in outside of GUI mode.
The tooltip displays context sensitive information on the selected GUI element, The tooltip displays context sensitive information on the selected GUI element,
such as weight, value, damage, armor rating, magical effects, and detailed description. such as weight, value, damage, armor rating, magical effects, and detailed description.
@ -82,7 +76,7 @@ This setting enables or disables the "red flash" overlay that provides a visual
If this setting is disabled, the player will "bleed" like NPCs do. If this setting is disabled, the player will "bleed" like NPCs do.
The default value is true. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
werewolf overlay werewolf overlay
---------------- ----------------
@ -91,16 +85,16 @@ werewolf overlay
:Range: True/False :Range: True/False
:Default: True :Default: True
Enable or disable the werewolf overlay. Enable or disable the werewolf visual effect in first-person mode.
The default value is true. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
color background owned color background owned
---------------------- ----------------------
:Type: RGBA floating point :Type: RGBA floating point
:Range: 0.0 to 1.0 :Range: 0.0 to 1.0
:Default: 0.15 0.0 0.0 1.0 :Default: 0.15 0.0 0.0 1.0 (dark red)
The following two settings determine the background color of the tool tip and the crosshair The following two settings determine the background color of the tool tip and the crosshair
when hovering over an item owned by an NPC. when hovering over an item owned by an NPC.
@ -108,7 +102,6 @@ The color definitions are composed of four floating point values between 0.0 and
representing the red, green, blue and alpha channels. The alpha value is currently ignored. representing the red, green, blue and alpha channels. The alpha value is currently ignored.
The crosshair color will have no effect if the crosshair setting in the HUD section is disabled. The crosshair color will have no effect if the crosshair setting in the HUD section is disabled.
The default value is "0.15 0.0 0.0 1.0", which is a dark red color.
This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
This setting has no effect if the show owned setting in the Game Settings Section is false. This setting has no effect if the show owned setting in the Game Settings Section is false.
@ -117,13 +110,12 @@ color crosshair owned
:Type: RGBA floating point :Type: RGBA floating point
:Range: 0.0 to 1.0 :Range: 0.0 to 1.0
:Default: 1.0 0.15 0.15 1.0 :Default: 1.0 0.15 0.15 1.0 (bright red)
This setting sets the color of the crosshair when hovering over an item owned by an NPC. This setting sets the color of the crosshair when hovering over an item owned by an NPC.
The value is composed of four floating point values representing the red, green, blue and alpha channels. The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored. The alpha value is currently ignored.
The default value is "1.0 0.15 0.15 1.0" which is a bright red color.
This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
This setting has no effect if the crosshair setting in the HUD Settings Section is false. This setting has no effect if the crosshair setting in the HUD Settings Section is false.
This setting has no effect if the show owned setting in the Game Settings Section is false. This setting has no effect if the show owned setting in the Game Settings Section is false.

View file

@ -8,9 +8,10 @@ crosshair
:Range: True/False :Range: True/False
:Default: True :Default: True
This setting determines whether the crosshair or reticle is displayed. This setting determines whether the crosshair or reticle is displayed. Enabling the crosshair provides more immediate feedback about which object is currently the focus of actions.
Some players perceive that disabling the crosshair provides a more immersive experience. Some players perceive that disabling the crosshair provides a more immersive experience.
Another common use is to disable the crosshair for screen shots. Another common use is to disable the crosshair for screen shots.
Enabling the crosshair provides more immediate feedback about which object is currently the focus of actions.
As an alternative to this setting, the complete GUI, including the crosshair, may be toggled at runtime with the F11 key.
This setting can be toggled with the Crosshair button in the Prefs panel of the Options menu. This setting can be toggled with the Crosshair button in the Prefs panel of the Options menu.

View file

@ -13,8 +13,7 @@ Values greater than approximately 18.0 will occasionally clip objects in the wor
Values greater than approximately 8.0 will clip the character's hands in first person view Values greater than approximately 8.0 will clip the character's hands in first person view
and/or the back of their head in third person view. and/or the back of their head in third person view.
The default value is 1.0. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
The value must be greater than 0.0, but it's unclear if the engine enforces this limitation.
small feature culling small feature culling
--------------------- ---------------------
@ -28,7 +27,7 @@ It generally improves performance to enable this feature,
and by definition the culled objects will be very small on screen. and by definition the culled objects will be very small on screen.
The size in pixels for an object to be considered 'small' is controlled by a separate setting. The size in pixels for an object to be considered 'small' is controlled by a separate setting.
The default value is true. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
small feature culling pixel size small feature culling pixel size
-------------------------------- --------------------------------
@ -88,7 +87,6 @@ Enabling the distant terrain setting is an alternative to increasing exterior ce
Note that the distant land setting does not include rendering of distant static objects, Note that the distant land setting does not include rendering of distant static objects,
so the resulting visual effect is not the same. so the resulting visual effect is not the same.
The default value is 6666.0.
This setting can be adjusted in game from the ridiculously low value of 2000.0 to a maximum of 6666.0 This setting can be adjusted in game from the ridiculously low value of 2000.0 to a maximum of 6666.0
using the View Distance slider in the Detail tab of the Video panel of the Options menu. using the View Distance slider in the Detail tab of the Video panel of the Options menu.
@ -105,8 +103,7 @@ while large values cause distortion at the edges of the screen.
The "field of view" setting interacts with aspect ratio of your video resolution in that more square aspect ratios The "field of view" setting interacts with aspect ratio of your video resolution in that more square aspect ratios
(e.g. 4:3) need a wider field of view to more resemble the same field of view on a widescreen (e.g. 16:9) monitor. (e.g. 4:3) need a wider field of view to more resemble the same field of view on a widescreen (e.g. 16:9) monitor.
The default value is 55.0. This setting can be changed in game using the Field of View slider This setting can be changed in game using the Field of View slider from the Video tab of the Video panel of the Options menu.
from the Video tab of the Video panel of the Options menu.
first person field of view first person field of view
-------------------------- --------------------------
@ -120,4 +117,4 @@ It is not recommended to change this value from its default value
because the Bethesda provided Morrowind assets do not adapt well to large values, because the Bethesda provided Morrowind assets do not adapt well to large values,
while small values can result in the hands not being visible. while small values can result in the hands not being visible.
The default value is 55.0. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.

View file

@ -9,8 +9,9 @@ exterior cell load distance
:Default: 1 :Default: 1
This setting determines the number of exterior cells adjacent to the character that will be loaded for rendering. This setting determines the number of exterior cells adjacent to the character that will be loaded for rendering.
Values greater than 1 may significantly affect loading times when exiting interior spaces
or loading additional exterior cells. Caution is advised when increasing this setting. .. Warning::
Values greater than 1 will significantly affect the frame rate and loading times. This setting is mainly intended for making screenshots of scenic vistas and not for real-time gameplay. Loading more cells can break certain scripts or quests in the game that expect cells to not be loaded until the player is there. These limitations will be addressed in a future version with a separate technique for rendering distant cells.
This setting interacts with viewing distance and field of view settings. This setting interacts with viewing distance and field of view settings.
@ -193,4 +194,4 @@ pointers cache size
:Range: >0 :Range: >0
:Default: 40 :Default: 40
The count of object pointers, that will be saved for a faster search by object ID. The count of object pointers that will be saved for a faster search by object ID. This is a temporary setting that can be used to mitigate scripting performance issues with certain game files. If your profiler (press F3 twice) displays a large overhead for the Scripting section, try increasing this setting.

View file

@ -16,7 +16,7 @@ If the setting is 2, the crosshair is the color of the color crosshair owned set
If the setting is 3, both the tool tip background and the crosshair are colored. If the setting is 3, both the tool tip background and the crosshair are colored.
The crosshair is not visible if crosshair is false. The crosshair is not visible if crosshair is false.
The default value is 0 (no clues). This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
show projectile damage show projectile damage
---------------------- ----------------------
@ -25,9 +25,9 @@ show projectile damage
:Range: True/False :Range: True/False
:Default: False :Default: False
If this setting is true, damage bonus of arrows and bolts will be showed on item tooltip. If this setting is true, the damage bonus of arrows and bolts will show on their tooltip.
The default value is false. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
show melee info show melee info
--------------- ---------------
@ -36,9 +36,9 @@ show melee info
:Range: True/False :Range: True/False
:Default: False :Default: False
If this setting is true, melee weapons reach and speed will be showed on item tooltip. If this setting is true, the reach and speed of melee weapons will show on their tooltip.
The default value is false. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
show enchant chance show enchant chance
------------------- -------------------
@ -49,7 +49,7 @@ show enchant chance
Whether or not the chance of success will be displayed in the enchanting menu. Whether or not the chance of success will be displayed in the enchanting menu.
The default value is false. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
best attack best attack
----------- -----------
@ -62,7 +62,6 @@ If this setting is true, the player character will always use the most powerful
(chop, slash or thrust). If this setting is false, (chop, slash or thrust). If this setting is false,
the type of attack is determined by the direction that the character is moving at the time the attack begins. the type of attack is determined by the direction that the character is moving at the time the attack begins.
The default value is false.
This setting can be toggled with the Always Use Best Attack button in the Prefs panel of the Options menu. This setting can be toggled with the Always Use Best Attack button in the Prefs panel of the Options menu.
can loot during death animation can loot during death animation
@ -79,7 +78,7 @@ This is how original Morrowind behaves.
If this setting is false, player has to wait until end of death animation in all cases. If this setting is false, player has to wait until end of death animation in all cases.
This case is more safe, but makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. This case is more safe, but makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder.
The default value is true. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
difficulty difficulty
---------- ----------
@ -91,12 +90,26 @@ difficulty
This setting adjusts the difficulty of the game and is intended to be in the range -100 to 100 inclusive. This setting adjusts the difficulty of the game and is intended to be in the range -100 to 100 inclusive.
Given the default game setting for fDifficultyMult of 5.0, Given the default game setting for fDifficultyMult of 5.0,
a value of -100 results in the player taking 80% of the usual damage, doing 6 times the normal damage. a value of -100 results in the player taking 80% of the usual damage, doing 6 times the normal damage.
A value of 100 results in the player taking 6 times as much damage, but inflicting only 80% of the usual damage. A value of 100 results in the player taking 6 times as much damage, while inflicting only 80% of the usual damage.
Values less than -500 will result in the player receiving no damage, Values below -500 will result in the player receiving no damage,
and values greater than 500 will result in the player inflicting no damage. and values above 500 will result in the player inflicting no damage.
This setting can be controlled in game with the Difficulty slider in the Prefs panel of the Options menu. This setting can be controlled in game with the Difficulty slider in the Prefs panel of the Options menu.
classic reflect absorb attribute behavior
-----------------------------------------
:Type: boolean
:Range: True/False
:Default: True
If this setting is true, "Absorb Attribute" spells which were reflected by the target are not "mirrored",
and the caster will absorb their own attribute resulting in no effect on both the caster and the target.
This makes the gameplay as a mage easier, but these spells become imbalanced.
This is how the original Morrowind behaves.
This setting can only be configured by editing the settings configuration file.
show effect duration show effect duration
-------------------- --------------------
@ -107,7 +120,19 @@ show effect duration
Show the remaining duration of magic effects and lights if this setting is true. Show the remaining duration of magic effects and lights if this setting is true.
The remaining duration is displayed in the tooltip by hovering over the magical effect. The remaining duration is displayed in the tooltip by hovering over the magical effect.
The default value is false. This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
enchanted weapons are magical
-----------------------------
:Type: boolean
:Range: True/False
:Default: True
Makes enchanted weapons without Magical flag bypass normal weapons resistance (and weakness) certain creatures have.
This is how original Morrowind behaves.
This setting can only be configured by editing the settings configuration file.
prevent merchant equipping prevent merchant equipping
-------------------------- --------------------------
@ -118,6 +143,8 @@ prevent merchant equipping
Prevents merchants from equipping items that are sold to them. Prevents merchants from equipping items that are sold to them.
This setting can only be configured by editing the settings configuration file.
followers attack on sight followers attack on sight
------------------------- -------------------------
@ -127,3 +154,6 @@ followers attack on sight
Makes player followers and escorters start combat with enemies who have started combat with them or the player. Makes player followers and escorters start combat with enemies who have started combat with them or the player.
Otherwise they wait for the enemies or the player to do an attack first. Otherwise they wait for the enemies or the player to do an attack first.
Please note this setting has not been extensively tested and could have side effects with certain quests.
This setting can only be configured by editing the settings configuration file.

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