From 0874d69546bf33c7527181f9788a469213cf7207 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Nov 2016 17:07:52 +0100 Subject: [PATCH 01/11] increased version number --- CMakeLists.txt | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d74e8cbc..6a74dde26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ endif() message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) -set(OPENMW_VERSION_MINOR 40) +set(OPENMW_VERSION_MINOR 41) set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_COMMITHASH "") diff --git a/README.md b/README.md index 3a6c4a75a..d38dfaeb2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ OpenMW is a recreation of the engine for the popular role-playing game Morrowind OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction Set. -* Version: 0.40.0 +* Version: 0.41.0 * License: GPLv3 (see [docs/license/GPL3.txt](https://github.com/OpenMW/openmw/blob/master/docs/license/GPL3.txt) for more information) * Website: http://www.openmw.org * IRC: #openmw on irc.freenode.net From f5943ccd5d78fa7e7575a9c0b49960446fe993db Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Nov 2016 17:09:53 +0100 Subject: [PATCH 02/11] updated changelog --- CHANGELOG.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0add2e02e..54b4bd34e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,78 @@ +0.41.0 +------ + + Bug #1138: Casting water walking doesn't move the player out of the water + Bug #1931: Rocks from blocked passage in Bamz-Amschend, Radacs Forge can reset and cant be removed again. + Bug #2048: Almvisi and Divine Intervention display wrong spell effect + Bug #2054: Show effect-indicator for "instant effect" spells and potions + Bug #2150: Clockwork City door animation problem + Bug #2288: Playback of weapon idle animation not correct + Bug #2410: Stat-review window doesn't display starting spells, powers, or abilities + Bug #2493: Repairing occasionally very slow + Bug #2716: [OSG] Water surface is too transparent from some angles + Bug #2859: [MAC OS X] Cannot exit fullscreen once enabled + Bug #3091: Editor: will not save addon if global variable value type is null + Bug #3277: Editor: Disabled nested tables in subviews aren't scrollable + Bug #3348: Disabled map markers show on minimap + Bug #3350: Extending selection to instances with same object results in duplicates. + Bug #3353: [Mod] Romance version 3.7 script failed + Bug #3376: [Mod] Vampire Embrace script fails to execute + Bug #3385: Banners don't animate in stormy weather as they do in the original game + Bug #3393: Akulakhan re-enabled after main quest + Bug #3427: Editor: OpenMW-CS instances won´t get deleted + Bug #3451: Feril Salmyn corpse isn't where it is supposed to be + Bug #3497: Zero-weight armor is displayed as "heavy" in inventory tooltip + Bug #3499: Idle animations don't always loop + Bug #3500: Spark showers at Sotha Sil do not appear until you look at the ceiling + Bug #3515: Editor: Moved objects in interior cells are teleported to exterior cells. + Bug #3520: Editor: OpenMW-CS cannot find project file when launching the game + Bug #3521: Armed NPCs don't use correct melee attacks + Bug #3535: Changing cell immediately after dying causes character to freeze. + Bug #3542: Unable to rest if unalerted slaughterfish are in the cell with you + Bug #3549: Blood effects occur even when a hit is resisted + Bug #3551: NPC Todwendy in german version can't interact + Bug #3552: Opening the journal when fonts are missing results in a crash + Bug #3555: SetInvisible command should not apply graphic effect + Bug #3561: Editor: changes from omwaddon are not loaded in [New Addon] mode + Bug #3562: Non-hostile NPCs can be disarmed by stealing their weapons via sneaking + Bug #3564: Editor: openmw-cs verification results + Bug #3568: Items that should be invisible are shown in the inventory + Bug #3574: Alchemy: Alembics and retorts are used in reverse + Bug #3575: Diaglog choices don't work in mw 0.40 + Bug #3576: Minor differences in AI reaction to hostile spell effects + Bug #3577: not local nolore dialog test + Bug #3578: Animation Replacer hangs after one cicle/step + Bug #3579: Bound Armor skillups and sounds + Bug #3583: Targetted GetCurrentAiPackage returns 0 + Bug #3584: Persuasion bug + Bug #3590: Vendor, Ilen Faveran, auto equips items from stock + Bug #3594: Weather doesn't seem to update correctly in Mournhold + Bug #3598: Saving doesn't save status of objects + Bug #3600: Screen goes black when trying to travel to Sadrith Mora + Bug #3608: Water ripples aren't created when walking on water + Bug #3626: Argonian NPCs swim like khajiits + Bug #3627: Cannot delete "Blessed touch" spell from spellbook + Bug #3634: An enchanted throwing weapon consumes charges from the stack in your inventory. (0.40.0) + Bug #3635: Levelled items in merchants are "re-rolled" (not bug 2952, see inside) + Feature #1118: AI combat: flee + Feature #1596: Editor: Render water + Feature #2042: Adding a non-portable Light to the inventory should cause the player to glow + Feature #3166: Editor: Instance editing mode - rotate sub mode + Feature #3167: Editor: Instance editing mode - scale sub mode + Feature #3420: ess-Importer: player control flags + Feature #3489: You shouldn't be be able to re-cast a bound equipment spell + Feature #3496: Zero-weight boots should play light boot footsteps + Feature #3516: Water Walking should give a "can't cast" message and fail when you are too deep + Feature #3519: Play audio and visual effects for all effects in a spell + Feature #3527: Double spell explosion scaling + Feature #3534: Play particle textures for spell effects + Feature #3539: Make NPCs use opponent's weapon range to decide whether to dodge + Feature #3540: Allow dodging for creatures with "biped" flag + Feature #3545: Drop shadow for items in menu + Feature #3558: Implement same spell range for "on touch" spells as original engine + Feature #3560: Allow using telekinesis with touch spells on objects + Task #3585: Some objects added by Morrowind Rebirth do not display properly their texture + 0.40.0 ------ From ee7f5d7d851c24d9bf795c4ff332097309404c74 Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Fri, 28 Oct 2016 15:39:27 +0200 Subject: [PATCH 03/11] [macOS] Move all configs & resources into app bundles Fixes #3566 (https://bugs.openmw.org/issues/3566). --- CMakeLists.txt | 38 ++++++++++++++++++---------------- apps/launcher/main.cpp | 8 ------- apps/opencs/CMakeLists.txt | 33 ++++++++++++++++++++++++++--- apps/opencs/main.cpp | 5 ----- apps/openmw/CMakeLists.txt | 15 ++++++++++++++ apps/wizard/main.cpp | 6 ------ components/files/macospath.cpp | 2 +- files/mygui/CMakeLists.txt | 6 +++++- files/shaders/CMakeLists.txt | 6 +++++- 9 files changed, 76 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a74dde26..d19745ff7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ endif() # Set up common paths if (APPLE) set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files") - set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files") + set(OPENMW_RESOURCE_FILES "../Resources/resources" CACHE PATH "location of OpenMW resources files") elseif(UNIX) # Paths SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries") @@ -286,6 +286,11 @@ endif (APPLE) # Set up DEBUG define set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1) +if (NOT APPLE) + set(OPENMW_MYGUI_FILES_ROOT ${OpenMW_BINARY_DIR}) + set(OPENMW_SHADERS_ROOT ${OpenMW_BINARY_DIR}) +endif () + add_subdirectory(files/) # Specify build paths @@ -307,11 +312,15 @@ endif (APPLE) configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg "${OpenMW_BINARY_DIR}/settings-default.cfg") -configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local - "${OpenMW_BINARY_DIR}/openmw.cfg") - -configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg - "${OpenMW_BINARY_DIR}/openmw.cfg.install") +if (NOT APPLE) + configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local + "${OpenMW_BINARY_DIR}/openmw.cfg") + configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg + "${OpenMW_BINARY_DIR}/openmw.cfg.install") +else () + configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg + "${OpenMW_BINARY_DIR}/openmw.cfg") +endif () configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg "${OpenMW_BINARY_DIR}/openmw-cs.cfg") @@ -714,14 +723,7 @@ if (APPLE) configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY) endif () - set(INSTALL_SUBDIR OpenMW) - - install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime) set(CPACK_GENERATOR "DragNDrop") set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) @@ -729,8 +731,8 @@ if (APPLE) set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) - set(INSTALLED_OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}") - set(INSTALLED_OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}") + set(INSTALLED_OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") + set(INSTALLED_OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${OPENCS_BUNDLE_NAME}") install(CODE " set(BU_CHMOD_BUNDLE_ITEMS ON) @@ -774,8 +776,8 @@ if (APPLE) set(${plugins_var} ${PLUGINS} PARENT_SCOPE) endfunction (install_plugins_for_bundle) - install_plugins_for_bundle("${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}" PLUGINS) - install_plugins_for_bundle("${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS) + install_plugins_for_bundle("${APP_BUNDLE_NAME}" PLUGINS) + install_plugins_for_bundle("${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS) set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}") set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}") diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index eadec64d0..96cadc8a7 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -35,14 +35,6 @@ int main(int argc, char *argv[]) // Now we make sure the current dir is set to application path QDir dir(QCoreApplication::applicationDirPath()); - #ifdef Q_OS_MAC - if (dir.dirName() == "MacOS") { - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - } - #endif - QDir::setCurrent(dir.absolutePath()); Launcher::MainDialog mainWin; diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index acf3cf021..e7e19be94 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -162,9 +162,15 @@ endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) if(APPLE) - set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns) + set (OPENCS_MAC_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns") + set (OPENCS_CFG "${OpenMW_BINARY_DIR}/openmw-cs.cfg") + set (OPENCS_DEFAULT_FILTERS_FILE "${OpenMW_BINARY_DIR}/resources/defaultfilters") + set (OPENCS_OPENMW_CFG "${OpenMW_BINARY_DIR}/openmw.cfg") else() set (OPENCS_MAC_ICON "") + set (OPENCS_CFG "") + set (OPENCS_DEFAULT_FILTERS_FILE "") + set (OPENCS_OPENMW_CFG "") endif(APPLE) add_executable(openmw-cs @@ -174,12 +180,23 @@ add_executable(openmw-cs ${OPENCS_MOC_SRC} ${OPENCS_RES_SRC} ${OPENCS_MAC_ICON} + ${OPENCS_CFG} + ${OPENCS_DEFAULT_FILTERS_FILE} + ${OPENCS_OPENMW_CFG} ) if(APPLE) + set(OPENCS_BUNDLE_NAME "OpenMW-CS") + set(OPENCS_BUNDLE_RESOURCES_DIR "${OpenMW_BINARY_DIR}/${OPENCS_BUNDLE_NAME}.app/Contents/Resources") + + set(OPENMW_MYGUI_FILES_ROOT ${OPENCS_BUNDLE_RESOURCES_DIR}) + set(OPENMW_SHADERS_ROOT ${OPENCS_BUNDLE_RESOURCES_DIR}) + + add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files) + set_target_properties(openmw-cs PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}" - OUTPUT_NAME "OpenMW-CS" + OUTPUT_NAME ${OPENCS_BUNDLE_NAME} MACOSX_BUNDLE_ICON_FILE "openmw-cs.icns" MACOSX_BUNDLE_BUNDLE_NAME "OpenCS" MACOSX_BUNDLE_GUI_IDENTIFIER "org.openmw.opencs" @@ -190,6 +207,16 @@ if(APPLE) set_source_files_properties(${OPENCS_MAC_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + set_source_files_properties(${OPENCS_CFG} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + set_source_files_properties(${OPENCS_DEFAULT_FILTERS_FILE} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources/resources) + set_source_files_properties(${OPENCS_OPENMW_CFG} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + + add_custom_command(TARGET openmw-cs + POST_BUILD + COMMAND cp "${OpenMW_BINARY_DIR}/resources/version" "${OPENCS_BUNDLE_RESOURCES_DIR}/resources") endif(APPLE) target_link_libraries(openmw-cs @@ -236,5 +263,5 @@ endif (MSVC) if(APPLE) - INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE) + INSTALL(TARGETS openmw-cs BUNDLE DESTINATION "." COMPONENT BUNDLE) endif() diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index c6fe34835..fc5e8fc7a 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -62,11 +62,6 @@ int main(int argc, char *argv[]) #ifdef Q_OS_MAC QDir dir(QCoreApplication::applicationDirPath()); - if (dir.dirName() == "MacOS") { - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - } QDir::setCurrent(dir.absolutePath()); #endif diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 452629fcf..ce859bc3e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -179,6 +179,21 @@ target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT}) endif() if(APPLE) + set(BUNDLE_RESOURCES_DIR "${APP_BUNDLE_DIR}/Contents/Resources") + + set(OPENMW_MYGUI_FILES_ROOT ${BUNDLE_RESOURCES_DIR}) + set(OPENMW_SHADERS_ROOT ${BUNDLE_RESOURCES_DIR}) + + add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files) + + configure_file("${OpenMW_BINARY_DIR}/settings-default.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY) + configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY) + configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY) + + add_custom_command(TARGET openmw + POST_BUILD + COMMAND cp "${OpenMW_BINARY_DIR}/resources/version" "${BUNDLE_RESOURCES_DIR}/resources") + find_library(COCOA_FRAMEWORK Cocoa) find_library(IOKIT_FRAMEWORK IOKit) target_link_libraries(openmw ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK}) diff --git a/apps/wizard/main.cpp b/apps/wizard/main.cpp index c861a4ac8..e3624742a 100644 --- a/apps/wizard/main.cpp +++ b/apps/wizard/main.cpp @@ -20,12 +20,6 @@ int main(int argc, char *argv[]) QDir dir(QCoreApplication::applicationDirPath()); #ifdef Q_OS_MAC - if (dir.dirName() == "MacOS") { - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - } - // force Qt to load only LOCAL plugins, don't touch system Qt installation QDir pluginsPath(QCoreApplication::applicationDirPath()); pluginsPath.cdUp(); diff --git a/components/files/macospath.cpp b/components/files/macospath.cpp index 237141960..b49b72e46 100644 --- a/components/files/macospath.cpp +++ b/components/files/macospath.cpp @@ -68,7 +68,7 @@ boost::filesystem::path MacOsPath::getCachePath() const boost::filesystem::path MacOsPath::getLocalPath() const { - return boost::filesystem::path("./"); + return boost::filesystem::path("../Resources/"); } boost::filesystem::path MacOsPath::getGlobalDataPath() const diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 7494d3ba2..6592de56e 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -1,6 +1,10 @@ +if (NOT DEFINED OPENMW_MYGUI_FILES_ROOT) + return() +endif() + # Copy resource files into the build directory set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui) +set(DDIR ${OPENMW_MYGUI_FILES_ROOT}/resources/mygui) set(MYGUI_FILES core.skin diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index 0738b5783..5ca0d1e83 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -1,6 +1,10 @@ +if (NOT DEFINED OPENMW_SHADERS_ROOT) + return() +endif() + # Copy resource files into the build directory set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(DDIR ${OpenMW_BINARY_DIR}/resources/shaders) +set(DDIR ${OPENMW_SHADERS_ROOT}/resources/shaders) set(SHADER_FILES water_vertex.glsl From 4f2a64ae17b7ffba56b2088a2e4c6902bfc6c911 Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Sun, 13 Nov 2016 15:40:54 +0100 Subject: [PATCH 04/11] [macOS] Set OpenMW working dir to /Contents/MacOS --- apps/openmw/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index cfe7fe305..43901d579 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -352,9 +352,8 @@ int main(int argc, char**argv) #endif #ifdef __APPLE__ - // FIXME: set current dir to bundle path - //boost::filesystem::path bundlePath = boost::filesystem::path(Ogre::macBundlePath()).parent_path(); - //boost::filesystem::current_path(bundlePath); + boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); + boost::filesystem::current_path(binary_path.parent_path()); #endif engine.reset(new OMW::Engine(cfgMgr)); From 9d8275580b390e59958fa79dac625c3e1eb966b4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 Dec 2016 02:25:05 +0100 Subject: [PATCH 05/11] Movement solver: performance improvement for the minimum stepping distance check, no need to waste time doing a second stepMove if we did not hit a slope or the step was already large enough to begin with. --- apps/openmw/mwphysics/physicssystem.cpp | 34 +++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index cc3ba40e1..fece18d20 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -69,7 +69,14 @@ namespace MWPhysics return osg::RadiansToDegrees(std::acos(normal * osg::Vec3f(0.f, 0.f, 1.f))); } - static bool stepMove(const btCollisionObject *colobj, osg::Vec3f &position, + enum StepMoveResult + { + Result_Blocked, // unable to move over obstacle + Result_MaxSlope, // unable to end movement on this slope + Result_Success + }; + + static StepMoveResult stepMove(const btCollisionObject *colobj, osg::Vec3f &position, const osg::Vec3f &toMove, float &remainingTime, const btCollisionWorld* collisionWorld) { /* @@ -120,7 +127,7 @@ namespace MWPhysics stepper.doTrace(colobj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), collisionWorld); if(stepper.mFraction < std::numeric_limits::epsilon()) - return false; // didn't even move the smallest representable amount + return Result_Blocked; // didn't even move the smallest representable amount // (TODO: shouldn't this be larger? Why bother with such a small amount?) /* @@ -138,7 +145,7 @@ namespace MWPhysics */ tracer.doTrace(colobj, stepper.mEndPos, stepper.mEndPos + toMove, collisionWorld); if(tracer.mFraction < std::numeric_limits::epsilon()) - return false; // didn't even move the smallest representable amount + return Result_Blocked; // didn't even move the smallest representable amount /* * Try moving back down sStepSizeDown using stepper. @@ -156,22 +163,22 @@ namespace MWPhysics * ============================================== */ stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld); - if(stepper.mFraction < 1.0f && getSlope(stepper.mPlaneNormal) <= sMaxSlope) + if (getSlope(stepper.mPlaneNormal) > sMaxSlope) + return Result_MaxSlope; + if(stepper.mFraction < 1.0f) { // don't allow stepping up other actors if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor) - return false; + return Result_Blocked; // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. // TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing // NOTE: caller's variables 'position' & 'remainingTime' are modified here position = stepper.mEndPos; remainingTime *= (1.0f-tracer.mFraction); // remaining time is proportional to remaining distance - return true; + return Result_Success; } - // moved between 0 and just under sStepSize distance but slope was too great, - // or moved full sStepSize distance (FIXME: is this a bug?) - return false; + return Result_Blocked; } @@ -361,14 +368,15 @@ namespace MWPhysics osg::Vec3f oldPosition = newPosition; // We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over) // NOTE: stepMove modifies newPosition if successful - bool result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld); - if (!result) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent + const float minStep = 10.f; + StepMoveResult result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld); + if (result == Result_MaxSlope && (velocity*remainingTime).length() < minStep) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent { osg::Vec3f normalizedVelocity = velocity; normalizedVelocity.normalize(); - result = stepMove(colobj, newPosition, normalizedVelocity*10.f, remainingTime, collisionWorld); + result = stepMove(colobj, newPosition, normalizedVelocity*minStep, remainingTime, collisionWorld); } - if(result) + if(result == Result_Success) { // don't let pure water creatures move out of water after stepMove if (ptr.getClass().isPureWaterCreature(ptr) From e5c9a82a296a9e02b57b5277bfae0bc60d424ecb Mon Sep 17 00:00:00 2001 From: Allofich Date: Mon, 5 Dec 2016 20:12:13 +0900 Subject: [PATCH 06/11] Fix fortify maximum magicka expiration (Fixes #3648) --- apps/openmw/mwmechanics/actors.cpp | 10 ++++++---- apps/openmw/mwmechanics/spellcasting.cpp | 7 +++++-- apps/openmw/mwmechanics/spellcasting.hpp | 4 +++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1a6a62fc3..2a5995e0c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -512,8 +512,8 @@ namespace MWMechanics if (magnitude > 0 && remainingTime > 0 && remainingTime < mDuration) { CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor); - effectTick(creatureStats, mActor, key, magnitude * remainingTime); - creatureStats.getMagicEffects().add(key, -magnitude); + if (effectTick(creatureStats, mActor, key, magnitude * remainingTime)) + creatureStats.getMagicEffects().add(key, -magnitude); } } }; @@ -527,8 +527,10 @@ namespace MWMechanics if (duration > 0) { - // apply correct magnitude for tickable effects that have just expired, - // in case duration > remaining time of effect + // Apply correct magnitude for tickable effects that have just expired, + // in case duration > remaining time of effect. + // One case where this will happen is when the player uses the rest/wait command + // while there is a tickable effect active that should expire before the end of the rest/wait. ExpiryVisitor visitor(ptr, duration); creatureStats.getActiveSpells().visitEffectSources(visitor); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 5c5fc3899..f06472103 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -1009,10 +1009,10 @@ namespace MWMechanics creatureStats.setDynamic(index, stat); } - void effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const EffectKey &effectKey, float magnitude) + bool effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const EffectKey &effectKey, float magnitude) { if (magnitude == 0.f) - return; + return false; bool receivedMagicDamage = false; @@ -1144,10 +1144,13 @@ namespace MWMechanics case ESM::MagicEffect::RemoveCurse: actor.getClass().getCreatureStats(actor).getSpells().purgeCurses(); break; + default: + return false; } if (receivedMagicDamage && actor == getPlayer()) MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); + return true; } } diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 852ae79dc..6e25acf50 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -63,7 +63,9 @@ namespace MWMechanics int getEffectiveEnchantmentCastCost (float castCost, const MWWorld::Ptr& actor); - void effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const MWMechanics::EffectKey& effectKey, float magnitude); + /// Apply a magic effect that is applied in tick intervals until its remaining time ends or it is removed + /// @return Was the effect a tickable effect with a magnitude? + bool effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const MWMechanics::EffectKey& effectKey, float magnitude); class CastSpell { From 19143f9bc7c48f8154ee1fcb86d879d11ef7334c Mon Sep 17 00:00:00 2001 From: Allofich Date: Tue, 6 Dec 2016 22:23:06 +0900 Subject: [PATCH 07/11] Require line of sight for AI attacks (Fixes #3646) --- apps/openmw/mwmechanics/aicombat.cpp | 54 +++++++++++++++------------- apps/openmw/mwmechanics/aicombat.hpp | 2 ++ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 80b343d4f..21eaa0de5 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -60,30 +60,30 @@ namespace MWMechanics FleeState_RunToDestination }; FleeState mFleeState; - bool mFleeLOS; - float mFleeUpdateLOSTimer; + bool mLOS; + float mUpdateLOSTimer; float mFleeBlindRunTimer; ESM::Pathgrid::Point mFleeDest; AiCombatStorage(): - mAttackCooldown(0), + mAttackCooldown(0.0f), mTimerReact(AI_REACTION_TIME), - mTimerCombatMove(0), + mTimerCombatMove(0.0f), mReadyToAttack(false), mAttack(false), - mAttackRange(0), + mAttackRange(0.0f), mCombatMove(false), mLastTargetPos(0,0,0), mCell(NULL), mCurrentAction(), - mActionCooldown(0), + mActionCooldown(0.0f), mStrength(), mForceNoShortcut(false), mShortcutFailPos(), mMovement(), mFleeState(FleeState_None), - mFleeLOS(false), - mFleeUpdateLOSTimer(0.0f), + mLOS(false), + mUpdateLOSTimer(0.0f), mFleeBlindRunTimer(0.0f) {} @@ -181,10 +181,14 @@ namespace MWMechanics if (!storage.isFleeing()) { - if (storage.mCurrentAction.get()) // need to wait to init action with it's attack range + if (storage.mCurrentAction.get()) // need to wait to init action with its attack range { - //Update every frame - bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, storage.mAttackRange); + //Update every frame. UpdateLOS uses a timer, so the LOS check does not happen every frame. + updateLOS(actor, target, duration, storage); + float targetReachedTolerance = 0.0f; + if (storage.mLOS) + targetReachedTolerance = storage.mAttackRange; + bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, targetReachedTolerance); if (is_target_reached) storage.mReadyToAttack = true; } @@ -283,7 +287,7 @@ namespace MWMechanics osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target); float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target); - storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack); + storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS); if (storage.mReadyToAttack) { @@ -309,18 +313,23 @@ namespace MWMechanics } } - void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage) + void MWMechanics::AiCombat::updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage) { static const float LOS_UPDATE_DURATION = 0.5f; - static const float BLIND_RUN_DURATION = 1.0f; - - if (storage.mFleeUpdateLOSTimer <= 0.f) + if (storage.mUpdateLOSTimer <= 0.f) { - storage.mFleeLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); - storage.mFleeUpdateLOSTimer = LOS_UPDATE_DURATION; + storage.mLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target); + storage.mUpdateLOSTimer = LOS_UPDATE_DURATION; } else - storage.mFleeUpdateLOSTimer -= duration; + storage.mUpdateLOSTimer -= duration; + } + + void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage) + { + static const float BLIND_RUN_DURATION = 1.0f; + + updateLOS(actor, target, duration, storage); AiCombatStorage::FleeState& state = storage.mFleeState; switch (state) @@ -332,7 +341,7 @@ namespace MWMechanics { float triggerDist = getMaxAttackDistance(target); - if (storage.mFleeLOS && + if (storage.mLOS && (triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist)) { const ESM::Pathgrid* pathgrid = @@ -399,7 +408,7 @@ namespace MWMechanics static const float fFleeDistance = MWBase::Environment::get().getWorld()->getStore().get().find("fFleeDistance")->getFloat(); float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length(); - if ((dist > fFleeDistance && !storage.mFleeLOS) + if ((dist > fFleeDistance && !storage.mLOS) || pathTo(actor, storage.mFleeDest, duration)) { state = AiCombatStorage::FleeState_Idle; @@ -602,9 +611,6 @@ namespace MWMechanics mMovement.mPosition[2] = 0; mFleeState = FleeState_None; mFleeDest = ESM::Pathgrid::Point(0, 0, 0); - mFleeLOS = false; - mFleeUpdateLOSTimer = 0.0f; - mFleeUpdateLOSTimer = 0.0f; } bool AiCombatStorage::isFleeing() diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 3f2bde776..a2e995cb3 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -61,6 +61,8 @@ namespace MWMechanics void attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController); + void updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage); + void updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage); /// Transfer desired movement (from AiCombatStorage) to Actor From b5e8c98b40c95cda7e2489e5cde2bf143b765544 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 17 Dec 2016 23:21:33 +0100 Subject: [PATCH 08/11] Enable waterCollision after moving the player above water (Fixes #3672) --- apps/openmw/mwphysics/physicssystem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index fece18d20..14bce06e3 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1349,7 +1349,8 @@ namespace MWPhysics else if (physicActor->getCollisionMode() && canMoveToWaterSurface(iter->first, waterlevel)) { const osg::Vec3f actorPosition = physicActor->getPosition(); - physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel)); + physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel)); + waterCollision = true; } } physicActor->setCanWaterWalk(waterCollision); From f2f0e9f1e71660d08bfc7df7509f7e3dc4faf246 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 16 Dec 2016 20:09:20 +0100 Subject: [PATCH 09/11] Clear the Skeleton's bone cache when a node is added/removed (Fixes #3663) --- apps/openmw/mwrender/creatureanimation.cpp | 2 -- apps/openmw/mwrender/npcanimation.cpp | 2 -- components/sceneutil/skeleton.cpp | 12 ++++++++++++ components/sceneutil/skeleton.hpp | 6 ++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index a095d5dd4..36a0f4085 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -110,8 +110,6 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot) osg::ref_ptr node = mResourceSystem->getSceneManager()->getInstance(item.getClass().getModel(item)); osg::ref_ptr attached = SceneUtil::attach(node, mObjectRoot, bonename, bonename); mResourceSystem->getSceneManager()->notifyAttached(attached); - if (mSkeleton) - mSkeleton->markDirty(); scene.reset(new PartHolder(attached)); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index d9dd1a89e..53eaf0996 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -671,8 +671,6 @@ PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, const st { osg::ref_ptr instance = mResourceSystem->getSceneManager()->getInstance(model); osg::ref_ptr attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, bonename); - if (mSkeleton) - mSkeleton->markDirty(); mResourceSystem->getSceneManager()->notifyAttached(attached); if (enchantedGlow) addGlow(attached, *glowColor); diff --git a/components/sceneutil/skeleton.cpp b/components/sceneutil/skeleton.cpp index 390a8e823..f3c2aef77 100644 --- a/components/sceneutil/skeleton.cpp +++ b/components/sceneutil/skeleton.cpp @@ -148,6 +148,8 @@ void Skeleton::markDirty() { mTraversedEvenFrame = false; mTraversedOddFrame = false; + mBoneCache.clear(); + mBoneCacheInit = false; } void Skeleton::traverse(osg::NodeVisitor& nv) @@ -160,6 +162,16 @@ void Skeleton::traverse(osg::NodeVisitor& nv) osg::Group::traverse(nv); } +void Skeleton::childInserted(unsigned int) +{ + markDirty(); +} + +void Skeleton::childRemoved(unsigned int, unsigned int) +{ + markDirty(); +} + Bone::Bone() : mNode(NULL) { diff --git a/components/sceneutil/skeleton.hpp b/components/sceneutil/skeleton.hpp index 764b7f645..24dcc6b3f 100644 --- a/components/sceneutil/skeleton.hpp +++ b/components/sceneutil/skeleton.hpp @@ -53,10 +53,12 @@ namespace SceneUtil bool getActive() const; - /// If a new RigGeometry is added after the Skeleton has already been rendered, you must call markDirty(). + void traverse(osg::NodeVisitor& nv); + void markDirty(); - void traverse(osg::NodeVisitor& nv); + virtual void childInserted(unsigned int); + virtual void childRemoved(unsigned int, unsigned int); private: // The root bone is not a "real" bone, it has no corresponding node in the scene graph. From 9c56ecac770dd22e107917840f59777b437d7b48 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 19 Dec 2016 15:28:27 +0100 Subject: [PATCH 10/11] fixed changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b4bd34e..87d826753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ Bug #2716: [OSG] Water surface is too transparent from some angles Bug #2859: [MAC OS X] Cannot exit fullscreen once enabled Bug #3091: Editor: will not save addon if global variable value type is null - Bug #3277: Editor: Disabled nested tables in subviews aren't scrollable + Bug #3277: Editor: Non-functional nested tables in subviews need to be hidden instead of being disabled Bug #3348: Disabled map markers show on minimap Bug #3350: Extending selection to instances with same object results in duplicates. Bug #3353: [Mod] Romance version 3.7 script failed From 87fd011a283188b51e6865644cb6dfa2b4eb657d Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Thu, 22 Dec 2016 20:48:58 +0100 Subject: [PATCH 11/11] Clean-up saves by dropping references with invalid RefNums (Fixes #1956) --- apps/openmw/mwworld/cellstore.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 5e65bad7c..ff3427e12 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -137,6 +137,9 @@ namespace iter->load (state); return; } + + std::cerr << "Dropping reference to " << state.mRef.mRefID << " (invalid content file link)" << std::endl; + return; } // new reference