diff --git a/.travis.yml b/.travis.yml index 1be8aa59cc..1fc85dca38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,14 @@ addons: build_command_prepend: "cmake ." build_command: "make -j3" branch_pattern: coverity_scan +matrix: + include: + - os: linux + env: + ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 " + compiler: clang + allow_failures: + - env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 " before_install: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi @@ -30,7 +38,7 @@ before_script: - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi script: - cd ./build - - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j4; fi + - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi after_script: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi diff --git a/AUTHORS.md b/AUTHORS.md index 90c543adae..0cd961c613 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -39,6 +39,7 @@ Programmers Eli2 Emanuel Guével (potatoesmaster) eroen + escondida Evgeniy Mineev (sandstranger) Fil Krynicki (filkry) Gašper Sedej diff --git a/CHANGELOG.md b/CHANGELOG.md index c2aa03dc2c..1766aa21d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +0.35.1 +------ + + Bug #781: incorrect trajectory of the sun + Bug #1079: Wrong starting position in "Character Stuff Wonderland" + Bug #1443: Repetitive taking of a stolen object is repetitively considered as a crime + Bug #1533: Divine Intervention goes to the wrong place. + Bug #1714: No visual indicator for time passed during training + Bug #1916: Telekinesis does not allow safe opening of traps + Bug #2227: Editor: addon file name inconsistency + Bug #2271: Player can melee enemies from water with impunity + Bug #2275: Objects with bigger scale move further using Move script + Bug #2285: Aryon's Dominator enchantment does not work properly + Bug #2290: No punishment for stealing gold from owned containers + Bug #2328: Launcher does not respond to Ctrl+C + Bug #2334: Drag-and-drop on a content file in the launcher creates duplicate items + Bug #2338: Arrows reclaimed from corpses do not stack sometimes + Bug #2344: Launcher - Settings importer running correctly? + Bug #2346: Launcher - Importing plugins into content list screws up the load order + Bug #2348: Mod: H.E.L.L.U.V.A. Handy Holdables does not appear in the content list + Bug #2353: Detect Animal detects dead creatures + Bug #2354: Cmake does not respect LIB_SUFFIX + Bug #2356: Active magic set inactive when switching magic items + Bug #2361: ERROR: ESM Error: Previous record contains unread bytes + Bug #2382: Switching spells with "next spell" or "previous spell" while holding shift promps delete spell dialog + Bug #2388: Regression: Can't toggle map on/off + Bug #2392: MOD Shrines - Restore Health and Cancel Options adds 100 health points + Bug #2394: List of Data Files tab in openmw-laucher needs to show all content files. + Bug #2402: Editor: skills saved incorrectly + Bug #2408: Equipping a constant effect Restore Health/Magicka/Fatigue item will permanently boost the stat it's restoring + Bug #2415: It is now possible to fall off the prison ship into the water when starting a new game + Bug #2419: MOD MCA crash to desktop + Bug #2420: Game crashes when character enters a certain area + Bug #2421: infinite loop when using cycle weapon without having a weapon + Feature #2221: Cannot dress dead NPCs + Feature #2349: Check CMake sets correct MSVC compiler settings for release build. + Feature #2397: Set default values for global mandatory records. + Feature #2412: Basic joystick support + 0.35.0 ------ diff --git a/CI/before_install.linux.sh b/CI/before_install.linux.sh index 998c285db2..27cb714638 100755 --- a/CI/before_install.linux.sh +++ b/CI/before_install.linux.sh @@ -1,7 +1,12 @@ #!/bin/sh -export CXX=g++ -export CC=gcc +if [ "${ANALYZE}" ]; then + if [ $(lsb_release -sc) = "precise" ]; then + echo "yes" | sudo apt-add-repository ppa:ubuntu-toolchain-r/test + fi + echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main" + wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add - +fi echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" echo "yes" | sudo apt-add-repository ppa:openmw/openmw @@ -10,6 +15,7 @@ sudo apt-get install -qq libgtest-dev google-mock sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev +if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi sudo mkdir /usr/src/gtest/build cd /usr/src/gtest/build sudo cmake .. -DBUILD_SHARED_LIBS=1 diff --git a/CI/before_script.linux.sh b/CI/before_script.linux.sh index b4889c9e17..71ddd20407 100755 --- a/CI/before_script.linux.sh +++ b/CI/before_script.linux.sh @@ -2,4 +2,6 @@ mkdir build cd build -cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE +export CODE_COVERAGE=1 +if [ "${CC}" = "clang" ]; then export CODE_COVERAGE=0; fi +${ANALYZE}cmake .. -DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c3d7c3783..07fffd5776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MINOR 35) -set(OPENMW_VERSION_RELEASE 0) +set(OPENMW_VERSION_RELEASE 1) set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_TAGHASH "") @@ -97,43 +97,6 @@ endif() # We probably support older versions than this. cmake_minimum_required(VERSION 2.6) -# source directory: libs - -set(LIBS_DIR ${CMAKE_SOURCE_DIR}/libs) - -set(OENGINE_OGRE - ${LIBS_DIR}/openengine/ogre/renderer.cpp - ${LIBS_DIR}/openengine/ogre/lights.cpp - ${LIBS_DIR}/openengine/ogre/selectionbuffer.cpp - ${LIBS_DIR}/openengine/ogre/imagerotate.cpp -) - -set(OENGINE_GUI - ${LIBS_DIR}/openengine/gui/loglistener.cpp - ${LIBS_DIR}/openengine/gui/manager.cpp - ${LIBS_DIR}/openengine/gui/layout.cpp -) - -set(OENGINE_BULLET - ${LIBS_DIR}/openengine/bullet/BtOgre.cpp - ${LIBS_DIR}/openengine/bullet/BtOgreExtras.h - ${LIBS_DIR}/openengine/bullet/BtOgreGP.h - ${LIBS_DIR}/openengine/bullet/BtOgrePG.h - ${LIBS_DIR}/openengine/bullet/physic.cpp - ${LIBS_DIR}/openengine/bullet/physic.hpp - ${LIBS_DIR}/openengine/bullet/BulletShapeLoader.cpp - ${LIBS_DIR}/openengine/bullet/BulletShapeLoader.h - ${LIBS_DIR}/openengine/bullet/trace.cpp - ${LIBS_DIR}/openengine/bullet/trace.h - -) - -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET}) -source_group(libs\\openengine FILES ${OENGINE_ALL}) - -set(OPENMW_LIBS ${OENGINE_ALL}) -set(OPENMW_LIBS_HEADER) - # Sound setup set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) unset(FFMPEG_LIBRARIES CACHE) @@ -266,7 +229,8 @@ endif () endif(WIN32) endif(OGRE_STATIC) -include_directories("." +include_directories("." ${LIBS_DIR} + SYSTEM ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS} ${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} @@ -275,7 +239,7 @@ include_directories("." ${MYGUI_INCLUDE_DIRS} ${MYGUI_PLATFORM_INCLUDE_DIRS} ${OPENAL_INCLUDE_DIR} - ${LIBS_DIR} + ${BULLET_INCLUDE_DIRS} ) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) @@ -375,6 +339,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) +configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt + "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt") + if (NOT WIN32 AND NOT APPLE) configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop "${OpenMW_BINARY_DIR}/openmw.desktop") @@ -382,22 +349,30 @@ if (NOT WIN32 AND NOT APPLE) "${OpenMW_BINARY_DIR}/openmw-cs.desktop") endif() -# Compiler settings -if (CMAKE_COMPILER_IS_GNUCC) - SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") +# CXX Compiler settings +if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long") + + if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE) + execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE CLANG_VERSION) + string(REGEX REPLACE ".*version ([0-9\\.]*).*" "\\1" CLANG_VERSION ${CLANG_VERSION}) + if ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression") + endif ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6) + endif(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) - if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) - SET(CMAKE_CXX_FLAGS "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}") - endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter") + endif(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) elseif (MSVC) # Enable link-time code generation globally for all linking set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG") -endif (CMAKE_COMPILER_IS_GNUCC) +endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) IF(NOT WIN32 AND NOT APPLE) # Linux building @@ -462,6 +437,8 @@ IF(NOT WIN32 AND NOT APPLE) INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") + IF(BUILD_OPENCS) INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") ENDIF(BUILD_OPENCS) @@ -482,6 +459,7 @@ if(WIN32) "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" + "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" "${OpenMW_BINARY_DIR}/Release/openmw.exe" DESTINATION ".") @@ -566,6 +544,10 @@ if(WIN32) include(CPack) endif(WIN32) +# Libs +include_directories(libs) +add_subdirectory(libs/openengine) + # Extern add_subdirectory (extern/shiny) add_subdirectory (extern/ogre-ffmpeg-videoplayer) @@ -699,61 +681,23 @@ if (WIN32) set(WARNINGS "${WARNINGS} /wd${d}") endforeach(d) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} ${MT_BUILD}") + # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here set(SHINY_WARNINGS "${WARNINGS} /wd4245") set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}") - set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") + # oics uses tinyxml, which has an initialized but unused variable set(OICS_WARNINGS "${WARNINGS} /wd4189") set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}") - set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - set_target_properties(ogre-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - if (BUILD_MYGUI_PLUGIN) - set_target_properties(Plugin_MyGUI_OpenMW_Resources PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_MYGUI_PLUGIN) - if (BUILD_LAUNCHER) - set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_LAUNCHER) - set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - if (BUILD_BSATOOL) - set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_BSATOOL) - if (BUILD_ESMTOOL) - set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_ESMTOOL) - if (BUILD_WIZARD) - set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS ${WARNINGS}) - endif (BUILD_WIZARD) + if (BUILD_OPENCS) # QT triggers an informational warning that the object layout may differ when compiled with /vd2 set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435") set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS}) endif (BUILD_OPENCS) - if (BUILD_ESSIMPORTER) - set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_ESSIMPORTER) - if (BUILD_MWINIIMPORTER) - set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") - endif (BUILD_MWINIIMPORTER) endif(MSVC) - # Same for MinGW - if (MINGW) - if (USE_DEBUG_CONSOLE) - set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,console") - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,console") - set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") - else(USE_DEBUG_CONSOLE) - set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,windows") - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,windows") - endif(USE_DEBUG_CONSOLE) - - set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "-Wl,-subsystem,console") - set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "-Wl,-subsystem,console") - set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") - endif(MINGW) - # TODO: At some point release builds should not use the console but rather write to a log file #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") @@ -767,6 +711,7 @@ if (APPLE) 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}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) diff --git a/README.md b/README.md index 63a3138960..aa5af0e6d7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ OpenMW OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -* Version: 0.35.0 +* Version: 0.35.1 * License: GPL (see docs/license/GPL3.txt for more information) * Website: http://www.openmw.org * IRC: #openmw on irc.freenode.net @@ -23,7 +23,7 @@ Getting Started * [Testing the game](https://wiki.openmw.org/index.php?title=Testing) * [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! -* [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](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) The data path ------------- @@ -68,9 +68,9 @@ Command line options of the blacklist is enabled) --script-blacklist-use [=arg(=1)] (=1) enable script blacklisting - --load-savegame arg load a save game file on game startup - (specify an absolute filename or a - filename relative to the current + --load-savegame arg load a save game file on game startup + (specify an absolute filename or a + filename relative to the current working directory) --skip-menu [=arg(=1)] (=0) skip main menu on game startup --new-game [=arg(=1)] (=0) run new game sequence (ignored if diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 98e18521e0..eef970d377 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -460,7 +460,7 @@ int clone(Arguments& info) for (Stats::iterator it = stats.begin(); it != stats.end(); ++it) { name.val = it->first; - float amount = it->second; + int amount = it->second; std::cout << std::setw(digitCount) << amount << " " << name.toString() << " "; if (++i % 3 == 0) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 97b0635fe5..2ee6c54bbf 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -6,6 +6,9 @@ #include +namespace +{ + void printAIPackage(ESM::AIPackage p) { std::cout << " AI Type: " << aiTypeLabel(p.mType) @@ -16,7 +19,7 @@ void printAIPackage(ESM::AIPackage p) std::cout << " Duration: " << p.mWander.mDuration << std::endl; std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl; if (p.mWander.mShouldRepeat != 1) - std::cout << " Should repeat: " << (bool)p.mWander.mShouldRepeat << std::endl; + std::cout << " Should repeat: " << (bool)(p.mWander.mShouldRepeat != 0) << std::endl; std::cout << " Idle: "; for (int i = 0; i != 8; i++) @@ -149,6 +152,26 @@ void printEffectList(ESM::EffectList effects) } } +void printTransport(const std::vector& transport) +{ + std::vector::const_iterator dit; + for (dit = transport.begin(); dit != transport.end(); ++dit) + { + std::cout << " Destination Position: " + << boost::format("%12.3f") % dit->mPos.pos[0] << "," + << boost::format("%12.3f") % dit->mPos.pos[1] << "," + << boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl; + std::cout << " Destination Rotation: " + << boost::format("%9.6f") % dit->mPos.rot[0] << "," + << boost::format("%9.6f") % dit->mPos.rot[1] << "," + << boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl; + if (dit->mCellName != "") + std::cout << " Destination Cell: " << dit->mCellName << std::endl; + } +} + +} + namespace EsmTool { RecordBase * @@ -631,6 +654,8 @@ void Record::print() for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) std::cout << " Spell: " << *sit << std::endl; + printTransport(mData.getTransport()); + std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl; @@ -1042,20 +1067,7 @@ void Record::print() for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) std::cout << " Spell: " << *sit << std::endl; - std::vector::iterator dit; - for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit) - { - std::cout << " Destination Position: " - << boost::format("%12.3f") % dit->mPos.pos[0] << "," - << boost::format("%12.3f") % dit->mPos.pos[1] << "," - << boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl; - std::cout << " Destination Rotation: " - << boost::format("%9.6f") % dit->mPos.rot[0] << "," - << boost::format("%9.6f") % dit->mPos.rot[1] << "," - << boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl; - if (dit->mCellName != "") - std::cout << " Destination Cell: " << dit->mCellName << std::endl; - } + printTransport(mData.getTransport()); std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; @@ -1253,7 +1265,7 @@ void Record::print() template<> void Record::print() { - std::cout << "Start Script: " << mData.mScript << std::endl; + std::cout << "Start Script: " << mData.mId << std::endl; std::cout << "Start Data: " << mData.mData << std::endl; } diff --git a/apps/essimporter/convertacdt.cpp b/apps/essimporter/convertacdt.cpp index 718403a8c3..55a20ec3df 100644 --- a/apps/essimporter/convertacdt.cpp +++ b/apps/essimporter/convertacdt.cpp @@ -23,18 +23,18 @@ namespace ESSImport } for (int i=0; i<8; ++i) { - cStats.mAttributes[i].mBase = acdt.mAttributes[i][1]; - cStats.mAttributes[i].mMod = acdt.mAttributes[i][0]; - cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0]; + cStats.mAttributes[i].mBase = static_cast(acdt.mAttributes[i][1]); + cStats.mAttributes[i].mMod = static_cast(acdt.mAttributes[i][0]); + cStats.mAttributes[i].mCurrent = static_cast(acdt.mAttributes[i][0]); } cStats.mGoldPool = acdt.mGoldPool; - cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer; - cStats.mAttacked = acdt.mFlags & Attacked; + cStats.mTalkedTo = (acdt.mFlags & TalkedToPlayer) != 0; + cStats.mAttacked = (acdt.mFlags & Attacked) != 0; } void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats) { - cStats.mDead = acsc.mFlags & Dead; + cStats.mDead = (acsc.mFlags & Dead) != 0; } void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats) diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index c23083f8e9..5711e6754b 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -553,7 +553,7 @@ public: ESM::WeatherState weather; weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather); weather.mNextWeather = toString(mGame.mGMDT.mNextWeather); - weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015*24*3600); + weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015f*24*3600); weather.mHour = mContext->mHour; weather.mWindSpeed = 0.f; weather.mTimePassed = 0.0; diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index cca356b2a8..442a7781c7 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -43,7 +43,7 @@ namespace ESSImport { unsigned int deleted; esm.getHT(deleted); - mDeleted = (deleted >> 24) & 0x2; // the other 3 bytes seem to be uninitialized garbage + mDeleted = ((deleted >> 24) & 0x2) != 0; // the other 3 bytes seem to be uninitialized garbage } if (esm.isNextSub("MVRF")) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index efebe5a4d0..479f8cba28 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -903,4 +903,4 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename std::cout << "content file: " << filename << " not found" << std::endl; } return writeTime; -} \ No newline at end of file +} diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 3c48fedc9a..a3f115fcf5 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -110,7 +110,7 @@ int wmain(int argc, wchar_t *wargv[]) { std::cerr << "cfg file does not exist" << std::endl; MwIniImporter importer; - importer.setVerbose(vm.count("verbose")); + importer.setVerbose(vm.count("verbose") != 0); // Font encoding settings std::string encoding(vm["encoding"].as()); diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c46f4e25d1..a53d786aa3 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp opencs_units (. editor) opencs_units (model/doc - document operation saving documentmanager loader runner + document operation saving documentmanager loader runner operationholder ) opencs_units_noqt (model/doc @@ -40,6 +40,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck + startscriptcheck search searchoperation searchstage ) @@ -91,7 +92,7 @@ opencs_hdrs_noqt (view/render opencs_units (view/tools - reportsubview reporttable + reportsubview reporttable searchsubview searchbox ) opencs_units_noqt (view/tools @@ -165,7 +166,8 @@ qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${BULLET_INCLUDE_DIRS}) +# for compiled .ui files +include_directories(${CMAKE_CURRENT_BINARY_DIR}) if(APPLE) set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns) @@ -175,7 +177,6 @@ endif(APPLE) add_executable(openmw-cs MACOSX_BUNDLE - ${OENGINE_BULLET} ${OPENCS_SRC} ${OPENCS_UI_HDR} ${OPENCS_MOC_SRC} @@ -199,6 +200,7 @@ if(APPLE) endif(APPLE) target_link_libraries(openmw-cs + ${OENGINE_LIBRARY} ${OGRE_LIBRARIES} ${OGRE_Overlay_LIBRARIES} ${OGRE_STATIC_PLUGINS} diff --git a/apps/opencs/model/doc/blacklist.cpp b/apps/opencs/model/doc/blacklist.cpp index 9b37a43024..0837264124 100644 --- a/apps/opencs/model/doc/blacklist.cpp +++ b/apps/opencs/model/doc/blacklist.cpp @@ -28,4 +28,4 @@ void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type, std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase); std::sort (list.begin(), list.end()); -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index e688a9474a..cb3b4ba187 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2254,7 +2254,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, mTools (*this), mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), - mSaving (*this, mProjectPath, encoding), + mSavingOperation (*this, mProjectPath, encoding), + mSaving (&mSavingOperation), mRunner (mProjectPath), mPhysics(boost::shared_ptr()) { if (mContentFiles.empty()) @@ -2373,6 +2374,17 @@ CSMWorld::UniversalId CSMDoc::Document::verify() return id; } + +CSMWorld::UniversalId CSMDoc::Document::newSearch() +{ + return mTools.newSearch(); +} + +void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search) +{ + return mTools.runSearch (searchId, search); +} + void CSMDoc::Document::abortOperation (int type) { if (type==State_Saving) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index f3aef6db63..6b1a1fc1e8 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -20,6 +20,7 @@ #include "saving.hpp" #include "blacklist.hpp" #include "runner.hpp" +#include "operationholder.hpp" class QAbstractItemModel; @@ -32,7 +33,7 @@ namespace ESM namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMWorld @@ -59,7 +60,8 @@ namespace CSMDoc CSMWorld::Data mData; CSMTools::Tools mTools; boost::filesystem::path mProjectPath; - Saving mSaving; + Saving mSavingOperation; + OperationHolder mSaving; boost::filesystem::path mResDir; Blacklist mBlacklist; Runner mRunner; @@ -118,6 +120,10 @@ namespace CSMDoc CSMWorld::UniversalId verify(); + CSMWorld::UniversalId newSearch(); + + void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search); + void abortOperation (int type); const CSMWorld::Data& getData() const; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 9b807225c9..7a1a86153d 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -107,4 +107,4 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std:: if (error.empty()) // do not remove the document yet, if we have an error removeDocument (document); -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index c545b9a9f0..0ae73e70c0 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -17,7 +17,7 @@ namespace Files { - class ConfigurationManager; + struct ConfigurationManager; } namespace CSMDoc @@ -50,7 +50,7 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. - void setResourceDir (const boost::filesystem::path& parResDir); + void setResourceDir (const boost::filesystem::path& parResDir); void setEncoding (ToUTF8::FromType encoding); @@ -61,7 +61,7 @@ namespace CSMDoc private: - boost::filesystem::path mResDir; + boost::filesystem::path mResDir; private slots: @@ -99,4 +99,4 @@ namespace CSMDoc }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 1fb423145a..9b295fb281 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -25,4 +25,4 @@ CSMDoc::Messages::Iterator CSMDoc::Messages::begin() const CSMDoc::Messages::Iterator CSMDoc::Messages::end() const { return mMessages.end(); -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index e728050f4f..3f1674f509 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -29,9 +29,9 @@ void CSMDoc::Operation::prepareStages() CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) : mType (type), mStages(std::vector >()), mCurrentStage(mStages.begin()), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), - mFinalAlways (finalAlways), mError(false) + mFinalAlways (finalAlways), mError(false), mConnected (false) { - connect (this, SIGNAL (finished()), this, SLOT (operationDone())); + mTimer = new QTimer (this); } CSMDoc::Operation::~Operation() @@ -42,15 +42,17 @@ CSMDoc::Operation::~Operation() void CSMDoc::Operation::run() { + mTimer->stop(); + + if (!mConnected) + { + connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage())); + mConnected = true; + } + prepareStages(); - QTimer timer; - - timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage())); - - timer.start (0); - - exec(); + mTimer->start (0); } void CSMDoc::Operation::appendStage (Stage *stage) @@ -65,7 +67,7 @@ bool CSMDoc::Operation::hasError() const void CSMDoc::Operation::abort() { - if (!isRunning()) + if (!mTimer->isActive()) return; mError = true; @@ -116,10 +118,11 @@ void CSMDoc::Operation::executeStage() emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); if (mCurrentStage==mStages.end()) - exit(); + operationDone(); } void CSMDoc::Operation::operationDone() { + mTimer->stop(); emit done (mType, mError); } diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 3c94677545..a6217fe2db 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -3,7 +3,8 @@ #include -#include +#include +#include namespace CSMWorld { @@ -14,7 +15,7 @@ namespace CSMDoc { class Stage; - class Operation : public QThread + class Operation : public QObject { Q_OBJECT @@ -27,6 +28,8 @@ namespace CSMDoc int mOrdered; bool mFinalAlways; bool mError; + bool mConnected; + QTimer *mTimer; void prepareStages(); @@ -38,8 +41,6 @@ namespace CSMDoc virtual ~Operation(); - virtual void run(); - void appendStage (Stage *stage); ///< The ownership of \a stage is transferred to *this. /// @@ -60,6 +61,8 @@ namespace CSMDoc void abort(); + void run(); + private slots: void executeStage(); @@ -68,4 +71,4 @@ namespace CSMDoc }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp new file mode 100644 index 0000000000..d79e140232 --- /dev/null +++ b/apps/opencs/model/doc/operationholder.cpp @@ -0,0 +1,65 @@ + +#include "operationholder.hpp" + +#include "operation.hpp" + +CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false) +{ + if (operation) + setOperation (operation); +} + +void CSMDoc::OperationHolder::setOperation (Operation *operation) +{ + mOperation = operation; + mOperation->moveToThread (&mThread); + + connect ( + mOperation, SIGNAL (progress (int, int, int)), + this, SIGNAL (progress (int, int, int))); + + connect ( + mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), + this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + + connect ( + mOperation, SIGNAL (done (int, bool)), + this, SLOT (doneSlot (int, bool))); + + connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort())); + + connect (&mThread, SIGNAL (started()), mOperation, SLOT (run())); +} + +bool CSMDoc::OperationHolder::isRunning() const +{ + return mRunning; +} + +void CSMDoc::OperationHolder::start() +{ + mRunning = true; + mThread.start(); +} + +void CSMDoc::OperationHolder::abort() +{ + mRunning = false; + emit abortSignal(); +} + +void CSMDoc::OperationHolder::abortAndWait() +{ + if (mRunning) + { + mThread.quit(); + mThread.wait(); + } +} + +void CSMDoc::OperationHolder::doneSlot (int type, bool failed) +{ + mRunning = false; + mThread.quit(); + emit done (type, failed); +} diff --git a/apps/opencs/model/doc/operationholder.hpp b/apps/opencs/model/doc/operationholder.hpp new file mode 100644 index 0000000000..6fe6df053c --- /dev/null +++ b/apps/opencs/model/doc/operationholder.hpp @@ -0,0 +1,56 @@ +#ifndef CSM_DOC_OPERATIONHOLDER_H +#define CSM_DOC_OPERATIONHOLDER_H + +#include +#include + +namespace CSMWorld +{ + class UniversalId; +} + +namespace CSMDoc +{ + class Operation; + + class OperationHolder : public QObject + { + Q_OBJECT + + QThread mThread; + Operation *mOperation; + bool mRunning; + + public: + + OperationHolder (Operation *operation = 0); + + void setOperation (Operation *operation); + + bool isRunning() const; + + void start(); + + void abort(); + + // Abort and wait until thread has finished. + void abortAndWait(); + + private slots: + + void doneSlot (int type, bool failed); + + signals: + + void progress (int current, int max, int type); + + void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint, int type); + + void done (int type, bool failed); + + void abortSignal(); + }; +} + +#endif diff --git a/apps/opencs/model/doc/runner.cpp b/apps/opencs/model/doc/runner.cpp index d679c18907..14fe0cda8f 100644 --- a/apps/opencs/model/doc/runner.cpp +++ b/apps/opencs/model/doc/runner.cpp @@ -6,7 +6,7 @@ #include #include -#include "operation.hpp" +#include "operationholder.hpp" CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath) : mRunning (false), mStartup (0), mProjectPath (projectPath) @@ -145,7 +145,7 @@ void CSMDoc::Runner::readyReadStandardOutput() } -CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation) +CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, OperationHolder *operation) : QObject (runner), mRunner (runner) { connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool))); diff --git a/apps/opencs/model/doc/runner.hpp b/apps/opencs/model/doc/runner.hpp index 38b52a73bd..517122492a 100644 --- a/apps/opencs/model/doc/runner.hpp +++ b/apps/opencs/model/doc/runner.hpp @@ -16,6 +16,8 @@ class QTemporaryFile; namespace CSMDoc { + class OperationHolder; + class Runner : public QObject { Q_OBJECT @@ -74,7 +76,7 @@ namespace CSMDoc public: /// *this attaches itself to runner - SaveWatcher (Runner *runner, Operation *operation); + SaveWatcher (Runner *runner, OperationHolder *operation); private slots: diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index 70e9e1d87c..9f6e469b8f 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -78,6 +78,9 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje appendStage (new WriteCollectionStage > (mDocument.getData().getMagicEffects(), mState)); + appendStage (new WriteCollectionStage > + (mDocument.getData().getStartScripts(), mState)); + appendStage (new WriteDialogueCollectionStage (mDocument, mState, false)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, true)); @@ -90,8 +93,12 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje appendStage (new WritePathgridCollectionStage (mDocument, mState)); + appendStage (new WriteLandCollectionStage (mDocument, mState)); + + appendStage (new WriteLandTextureCollectionStage (mDocument, mState)); + // close file and clean up appendStage (new CloseSaveStage (mState)); appendStage (new FinalSavingStage (mDocument, mState)); -} \ No newline at end of file +} diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 08f8c9eaa8..ef7d1d3af5 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -90,7 +90,7 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document, SavingState& state, bool journal) -: mDocument (document), mState (state), +: mState (state), mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()), mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos()) {} @@ -353,6 +353,74 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message } +CSMDoc::WriteLandCollectionStage::WriteLandCollectionStage (Document& document, + SavingState& state) +: mDocument (document), mState (state) +{} + +int CSMDoc::WriteLandCollectionStage::setup() +{ + return mDocument.getData().getLand().getSize(); +} + +void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages) +{ + const CSMWorld::Record& land = + mDocument.getData().getLand().getRecord (stage); + + if (land.mState==CSMWorld::RecordBase::State_Modified || + land.mState==CSMWorld::RecordBase::State_ModifiedOnly) + { + CSMWorld::Land record = land.get(); + + mState.getWriter().startRecord (record.mLand->sRecordId); + + record.mLand->save (mState.getWriter()); + if(record.mLand->mLandData) + record.mLand->mLandData->save (mState.getWriter()); + + mState.getWriter().endRecord (record.mLand->sRecordId); + } + else if (land.mState==CSMWorld::RecordBase::State_Deleted) + { + /// \todo write record with delete flag + } +} + + +CSMDoc::WriteLandTextureCollectionStage::WriteLandTextureCollectionStage (Document& document, + SavingState& state) +: mDocument (document), mState (state) +{} + +int CSMDoc::WriteLandTextureCollectionStage::setup() +{ + return mDocument.getData().getLandTextures().getSize(); +} + +void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages) +{ + const CSMWorld::Record& landTexture = + mDocument.getData().getLandTextures().getRecord (stage); + + if (landTexture.mState==CSMWorld::RecordBase::State_Modified || + landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly) + { + CSMWorld::LandTexture record = landTexture.get(); + + mState.getWriter().startRecord (record.sRecordId); + + record.save (mState.getWriter()); + + mState.getWriter().endRecord (record.sRecordId); + } + else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted) + { + /// \todo write record with delete flag + } +} + + CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state) : mState (state) {} diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 87c9ba7eb8..188f22f961 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -7,6 +7,8 @@ #include "../world/idcollection.hpp" #include "../world/scope.hpp" +#include + #include "savingstate.hpp" namespace ESM @@ -103,8 +105,15 @@ namespace CSMDoc if (state==CSMWorld::RecordBase::State_Modified || state==CSMWorld::RecordBase::State_ModifiedOnly) { - mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); - mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); + // FIXME: A quick Workaround to support records which should not write + // NAME, including SKIL, MGEF and SCPT. If there are many more + // idcollection records that doesn't use NAME then a more generic + // solution may be required. + uint32_t name = mCollection.getRecord (stage).mModified.sRecordId; + mState.getWriter().startRecord (name); + + if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT) + mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); mCollection.getRecord (stage).mModified.save (mState.getWriter()); mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId); } @@ -117,7 +126,6 @@ namespace CSMDoc class WriteDialogueCollectionStage : public Stage { - Document& mDocument; SavingState& mState; const CSMWorld::IdCollection& mTopics; CSMWorld::InfoCollection& mInfos; @@ -200,6 +208,40 @@ namespace CSMDoc ///< Messages resulting from this stage will be appended to \a messages. }; + + class WriteLandCollectionStage : public Stage + { + Document& mDocument; + SavingState& mState; + + public: + + WriteLandCollectionStage (Document& document, SavingState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + + + class WriteLandTextureCollectionStage : public Stage + { + Document& mDocument; + SavingState& mState; + + public: + + WriteLandTextureCollectionStage (Document& document, SavingState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + class CloseSaveStage : public Stage { SavingState& mState; diff --git a/apps/opencs/model/doc/stage.cpp b/apps/opencs/model/doc/stage.cpp index 99b7657709..1a2c5c721f 100644 --- a/apps/opencs/model/doc/stage.cpp +++ b/apps/opencs/model/doc/stage.cpp @@ -1,4 +1,4 @@ #include "stage.hpp" -CSMDoc::Stage::~Stage() {} \ No newline at end of file +CSMDoc::Stage::~Stage() {} diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp index 287439a8bb..78f4681010 100644 --- a/apps/opencs/model/doc/state.hpp +++ b/apps/opencs/model/doc/state.hpp @@ -13,7 +13,7 @@ namespace CSMDoc State_Saving = 16, State_Verifying = 32, State_Compiling = 64, // not implemented yet - State_Searching = 128, // not implemented yet + State_Searching = 128, State_Loading = 256 // pseudo-state; can not be encountered in a loaded document }; } diff --git a/apps/opencs/model/filter/booleannode.cpp b/apps/opencs/model/filter/booleannode.cpp index 2daa1b6d81..35fc98e085 100644 --- a/apps/opencs/model/filter/booleannode.cpp +++ b/apps/opencs/model/filter/booleannode.cpp @@ -12,4 +12,4 @@ bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row, std::string CSMFilter::BooleanNode::toString (bool numericColumns) const { return mTrue ? "true" : "false"; -} \ No newline at end of file +} diff --git a/apps/opencs/model/filter/booleannode.hpp b/apps/opencs/model/filter/booleannode.hpp index d9635746c0..32206b5753 100644 --- a/apps/opencs/model/filter/booleannode.hpp +++ b/apps/opencs/model/filter/booleannode.hpp @@ -26,4 +26,4 @@ namespace CSMFilter }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/filter/node.cpp b/apps/opencs/model/filter/node.cpp index 276861cdc4..091dc46988 100644 --- a/apps/opencs/model/filter/node.cpp +++ b/apps/opencs/model/filter/node.cpp @@ -3,4 +3,4 @@ CSMFilter::Node::Node() {} -CSMFilter::Node::~Node() {} \ No newline at end of file +CSMFilter::Node::~Node() {} diff --git a/apps/opencs/model/filter/notnode.cpp b/apps/opencs/model/filter/notnode.cpp index 2317730753..b5d9da7b7d 100644 --- a/apps/opencs/model/filter/notnode.cpp +++ b/apps/opencs/model/filter/notnode.cpp @@ -7,4 +7,4 @@ bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row, const std::map& columns) const { return !getChild().test (table, row, columns); -} \ No newline at end of file +} diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index 24cdce4f5f..73c378f113 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -82,4 +82,4 @@ std::string CSMFilter::TextNode::toString (bool numericColumns) const stream << ", \"" << mText << "\")"; return stream.str(); -} \ No newline at end of file +} diff --git a/apps/opencs/model/filter/unarynode.cpp b/apps/opencs/model/filter/unarynode.cpp index 43a24b76a1..c40d191b62 100644 --- a/apps/opencs/model/filter/unarynode.cpp +++ b/apps/opencs/model/filter/unarynode.cpp @@ -23,4 +23,4 @@ std::vector CSMFilter::UnaryNode::getReferencedColumns() const std::string CSMFilter::UnaryNode::toString (bool numericColumns) const { return mName + " " + mChild->toString (numericColumns); -} \ No newline at end of file +} diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 26b9824418..72cf5896bf 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -94,4 +94,4 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const stream << ")"; return stream.str(); -} \ No newline at end of file +} diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 7dac660c35..7a975c99c4 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -208,6 +208,21 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:

" + toolTip); } + declareSection ("search", "Search & Replace"); + { + Setting *before = createSetting (Type_SpinBox, "char-before", + "Characters before search string"); + before->setDefaultValue (10); + before->setRange (0, 1000); + before->setToolTip ("Maximum number of character to display in search result before the searched text"); + + Setting *after = createSetting (Type_SpinBox, "char-after", + "Characters after search string"); + after->setDefaultValue (10); + after->setRange (0, 1000); + after->setToolTip ("Maximum number of character to display in search result after the searched text"); + } + { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/model/tools/birthsigncheck.cpp b/apps/opencs/model/tools/birthsigncheck.cpp index 1d72e24b87..4e6da4631f 100644 --- a/apps/opencs/model/tools/birthsigncheck.cpp +++ b/apps/opencs/model/tools/birthsigncheck.cpp @@ -41,4 +41,4 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag /// \todo test if the texture exists /// \todo check data members that can't be edited in the table view -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/bodypartcheck.hpp b/apps/opencs/model/tools/bodypartcheck.hpp index 0a6ca959ac..dbab5f5c60 100644 --- a/apps/opencs/model/tools/bodypartcheck.hpp +++ b/apps/opencs/model/tools/bodypartcheck.hpp @@ -32,4 +32,4 @@ namespace CSMTools }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index 5b872a2668..be57a37290 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -65,4 +65,4 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages) messages.push_back (std::make_pair (id, ESM::Skill::indexToId (iter->first) + " is listed more than once")); } -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index 87d19401ba..4c97d22665 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -20,4 +20,4 @@ void CSMTools::MandatoryIdStage::perform (int stage, CSMDoc::Messages& messages) if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) messages.add (mCollectionId, "Missing mandatory record: " + mIds.at (stage)); -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 143d617721..3b2c8d290e 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -70,4 +70,4 @@ void CSMTools::RaceCheckStage::perform (int stage, CSMDoc::Messages& messages) performFinal (messages); else performPerRecord (stage, messages); -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/referencecheck.cpp b/apps/opencs/model/tools/referencecheck.cpp index 0c1d7d38f3..198c3627f4 100644 --- a/apps/opencs/model/tools/referencecheck.cpp +++ b/apps/opencs/model/tools/referencecheck.cpp @@ -48,10 +48,6 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message } } - // Check if referenced object is in valid cell - if (mCells.searchId(cellRef.mCell) == -1) - messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell)); - // If object have owner, check if that owner reference is valid if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1) messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner)); @@ -70,9 +66,9 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message // Check item's faction rank if (hasFaction && cellRef.mFactionRank < -1) - messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + cellRef.mFactionRank)); + messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + boost::lexical_cast(cellRef.mFactionRank))); else if (!hasFaction && cellRef.mFactionRank != -2) - messages.push_back(std::make_pair(id, " has invalid faction rank " + cellRef.mFactionRank)); + messages.push_back(std::make_pair(id, " has invalid faction rank " + boost::lexical_cast(cellRef.mFactionRank))); // If door have destination cell, check if that reference is valid if (!cellRef.mDestCell.empty()) diff --git a/apps/opencs/model/tools/referencecheck.hpp b/apps/opencs/model/tools/referencecheck.hpp index 9cf685b3ad..70ef029165 100644 --- a/apps/opencs/model/tools/referencecheck.hpp +++ b/apps/opencs/model/tools/referencecheck.hpp @@ -26,4 +26,4 @@ namespace CSMTools }; } -#endif // CSM_TOOLS_REFERENCECHECK_H \ No newline at end of file +#endif // CSM_TOOLS_REFERENCECHECK_H diff --git a/apps/opencs/model/tools/regioncheck.cpp b/apps/opencs/model/tools/regioncheck.cpp index 091836d0d7..42abc35c93 100644 --- a/apps/opencs/model/tools/regioncheck.cpp +++ b/apps/opencs/model/tools/regioncheck.cpp @@ -35,4 +35,4 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages) /// \todo test that the ID in mSleeplist exists /// \todo check data members that can't be edited in the table view -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index 1354206128..5648ace549 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -2,6 +2,29 @@ #include "reportmodel.hpp" #include +#include + +#include "../world/columns.hpp" + +CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint) +: mId (id), mMessage (message), mHint (hint) +{} + +CSMTools::ReportModel::ReportModel (bool fieldColumn) +{ + if (fieldColumn) + { + mColumnField = 3; + mColumnDescription = 4; + } + else + { + mColumnDescription = 3; + + mColumnField = -1; + } +} int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const { @@ -16,7 +39,7 @@ int CSMTools::ReportModel::columnCount (const QModelIndex & parent) const if (parent.isValid()) return 0; - return 3; + return mColumnDescription+1; } QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const @@ -24,13 +47,49 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const if (role!=Qt::DisplayRole) return QVariant(); - if (index.column()==0) - return static_cast (mRows.at (index.row()).first.getType()); + switch (index.column()) + { + case Column_Type: - if (index.column()==1) - return QString::fromUtf8 (mRows.at (index.row()).second.first.c_str()); + return static_cast (mRows.at (index.row()).mId.getType()); + + case Column_Id: + { + CSMWorld::UniversalId id = mRows.at (index.row()).mId; - return QString::fromUtf8 (mRows.at (index.row()).second.second.c_str()); + if (id.getArgumentType()==CSMWorld::UniversalId::ArgumentType_Id) + return QString::fromUtf8 (id.getId().c_str()); + + return QString ("-"); + } + + case Column_Hint: + + return QString::fromUtf8 (mRows.at (index.row()).mHint.c_str()); + } + + if (index.column()==mColumnDescription) + return QString::fromUtf8 (mRows.at (index.row()).mMessage.c_str()); + + if (index.column()==mColumnField) + { + std::string field; + + std::istringstream stream (mRows.at (index.row()).mHint); + + char type, ignore; + int fieldIndex; + + if ((stream >> type >> ignore >> fieldIndex) && (type=='r' || type=='R')) + { + field = CSMWorld::Columns::getName ( + static_cast (fieldIndex)); + } + + return QString::fromUtf8 (field.c_str()); + } + + return QVariant(); } QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const @@ -41,13 +100,19 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta if (orientation==Qt::Vertical) return QVariant(); - if (section==0) - return "Type"; + switch (section) + { + case Column_Type: return "Type"; + case Column_Id: return "ID"; + } - if (section==1) + if (section==mColumnDescription) return "Description"; - return "Hint"; + if (section==mColumnField) + return "Field"; + + return "-"; } bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent) @@ -64,18 +129,43 @@ void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::str const std::string& hint) { beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - - mRows.push_back (std::make_pair (id, std::make_pair (message, hint))); + + mRows.push_back (Line (id, message, hint)); endInsertRows(); } +void CSMTools::ReportModel::flagAsReplaced (int index) +{ + Line& line = mRows.at (index); + std::string hint = line.mHint; + + if (hint.empty() || hint[0]!='R') + throw std::logic_error ("trying to flag message as replaced that is not replaceable"); + + hint[0] = 'r'; + + line.mHint = hint; + + emit dataChanged (this->index (index, 0), this->index (index, columnCount())); +} + const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const { - return mRows.at (row).first; + return mRows.at (row).mId; } std::string CSMTools::ReportModel::getHint (int row) const { - return mRows.at (row).second.second; -} \ No newline at end of file + return mRows.at (row).mHint; +} + +void CSMTools::ReportModel::clear() +{ + if (!mRows.empty()) + { + beginRemoveRows (QModelIndex(), 0, mRows.size()-1); + mRows.clear(); + endRemoveRows(); + } +} diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 709e024a72..4d2d0542f5 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -14,10 +14,32 @@ namespace CSMTools { Q_OBJECT - std::vector > > mRows; + struct Line + { + Line (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint); + + CSMWorld::UniversalId mId; + std::string mMessage; + std::string mHint; + }; + + std::vector mRows; + + // Fixed columns + enum Columns + { + Column_Type = 0, Column_Id = 1, Column_Hint = 2 + }; + + // Configurable columns + int mColumnDescription; + int mColumnField; public: + ReportModel (bool fieldColumn = false); + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; @@ -27,13 +49,17 @@ namespace CSMTools virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - + void add (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint = ""); + void flagAsReplaced (int index); + const CSMWorld::UniversalId& getUniversalId (int row) const; std::string getHint (int row) const; + + void clear(); }; } diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index d9dea7f43c..a70ee2ae4a 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -98,4 +98,4 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) } mMessages = 0; -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/search.cpp b/apps/opencs/model/tools/search.cpp new file mode 100644 index 0000000000..cb88507547 --- /dev/null +++ b/apps/opencs/model/tools/search.cpp @@ -0,0 +1,279 @@ + +#include "search.hpp" + +#include +#include + +#include "../doc/messages.hpp" +#include "../doc/document.hpp" + +#include "../world/idtablebase.hpp" +#include "../world/columnbase.hpp" +#include "../world/universalid.hpp" +#include "../world/commands.hpp" + +void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model, + const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, + CSMDoc::Messages& messages) const +{ + // using QString here for easier handling of case folding. + + QString search = QString::fromUtf8 (mText.c_str()); + QString text = model->data (index).toString(); + + int pos = 0; + + while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1) + { + std::ostringstream hint; + hint + << (writable ? 'R' : 'r') + <<": " + << model->getColumnId (index.column()) + << " " << pos + << " " << search.length(); + + messages.add (id, formatDescription (text, pos, search.length()).toUtf8().data(), hint.str()); + + pos += search.length(); + } +} + +void CSMTools::Search::searchRegExCell (const CSMWorld::IdTableBase *model, + const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, + CSMDoc::Messages& messages) const +{ + QString text = model->data (index).toString(); + + int pos = 0; + + while ((pos = mRegExp.indexIn (text, pos))!=-1) + { + int length = mRegExp.matchedLength(); + + std::ostringstream hint; + hint + << (writable ? 'R' : 'r') + <<": " + << model->getColumnId (index.column()) + << " " << pos + << " " << length; + + messages.add (id, formatDescription (text, pos, length).toUtf8().data(), hint.str()); + + pos += length; + } +} + +void CSMTools::Search::searchRecordStateCell (const CSMWorld::IdTableBase *model, + const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const +{ + if (writable) + throw std::logic_error ("Record state can not be modified by search and replace"); + + int data = model->data (index).toInt(); + + if (data==mValue) + { + std::vector states = + CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification); + + std::ostringstream message; + message << states.at (data); + + std::ostringstream hint; + hint << "r: " << model->getColumnId (index.column()); + + messages.add (id, message.str(), hint.str()); + } +} + +QString CSMTools::Search::formatDescription (const QString& description, int pos, int length) const +{ + QString text (description); + + // split + QString highlight = flatten (text.mid (pos, length)); + QString before = flatten (mPaddingBefore>=pos ? + text.mid (0, pos) : text.mid (pos-mPaddingBefore, mPaddingBefore)); + QString after = flatten (text.mid (pos+length, mPaddingAfter)); + + // compensate for Windows nonsense + text.remove ('\r'); + + // join + text = before + "" + highlight + "" + after; + + // improve layout for single line display + text.replace ("\n", "<CR>"); + text.replace ('\t', ' '); + + return text; +} + +QString CSMTools::Search::flatten (const QString& text) const +{ + QString flat (text); + + flat.replace ("&", "&"); + flat.replace ("<", "<"); + + return flat; +} + +CSMTools::Search::Search() : mType (Type_None), mPaddingBefore (10), mPaddingAfter (10) {} + +CSMTools::Search::Search (Type type, const std::string& value) +: mType (type), mText (value), mPaddingBefore (10), mPaddingAfter (10) +{ + if (type!=Type_Text && type!=Type_Id) + throw std::logic_error ("Invalid search parameter (string)"); +} + +CSMTools::Search::Search (Type type, const QRegExp& value) +: mType (type), mRegExp (value), mPaddingBefore (10), mPaddingAfter (10) +{ + if (type!=Type_TextRegEx && type!=Type_IdRegEx) + throw std::logic_error ("Invalid search parameter (RegExp)"); +} + +CSMTools::Search::Search (Type type, int value) +: mType (type), mValue (value), mPaddingBefore (10), mPaddingAfter (10) +{ + if (type!=Type_RecordState) + throw std::logic_error ("invalid search parameter (int)"); +} + +void CSMTools::Search::configure (const CSMWorld::IdTableBase *model) +{ + mColumns.clear(); + + int columns = model->columnCount(); + + for (int i=0; i ( + model->headerData ( + i, Qt::Horizontal, static_cast (CSMWorld::ColumnBase::Role_Display)).toInt()); + + bool consider = false; + + switch (mType) + { + case Type_Text: + case Type_TextRegEx: + + if (CSMWorld::ColumnBase::isText (display) || + CSMWorld::ColumnBase::isScript (display)) + { + consider = true; + } + + break; + + case Type_Id: + case Type_IdRegEx: + + if (CSMWorld::ColumnBase::isId (display) || + CSMWorld::ColumnBase::isScript (display)) + { + consider = true; + } + + break; + + case Type_RecordState: + + if (display==CSMWorld::ColumnBase::Display_RecordState) + consider = true; + + break; + + case Type_None: + + break; + } + + if (consider) + mColumns.insert (i); + } + + mIdColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_Id); + mTypeColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); +} + +void CSMTools::Search::searchRow (const CSMWorld::IdTableBase *model, int row, + CSMDoc::Messages& messages) const +{ + for (std::set::const_iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter) + { + QModelIndex index = model->index (row, *iter); + + CSMWorld::UniversalId::Type type = static_cast ( + model->data (model->index (row, mTypeColumn)).toInt()); + + CSMWorld::UniversalId id ( + type, model->data (model->index (row, mIdColumn)).toString().toUtf8().data()); + + bool writable = model->flags (index) & Qt::ItemIsEditable; + + switch (mType) + { + case Type_Text: + case Type_Id: + + searchTextCell (model, index, id, writable, messages); + break; + + case Type_TextRegEx: + case Type_IdRegEx: + + searchRegExCell (model, index, id, writable, messages); + break; + + case Type_RecordState: + + searchRecordStateCell (model, index, id, writable, messages); + break; + + case Type_None: + + break; + } + } +} + +void CSMTools::Search::setPadding (int before, int after) +{ + mPaddingBefore = before; + mPaddingAfter = after; +} + +void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model, + const CSMWorld::UniversalId& id, const std::string& messageHint, + const std::string& replaceText) const +{ + std::istringstream stream (messageHint.c_str()); + + char hint, ignore; + int columnId, pos, length; + + if (stream >> hint >> ignore >> columnId >> pos >> length) + { + int column = + model->findColumnIndex (static_cast (columnId)); + + QModelIndex index = model->getModelIndex (id.getId(), column); + + std::string text = model->data (index).toString().toUtf8().constData(); + + std::string before = text.substr (0, pos); + std::string after = text.substr (pos+length); + + std::string newText = before + replaceText + after; + + document.getUndoStack().push ( + new CSMWorld::ModifyCommand (*model, index, QString::fromUtf8 (newText.c_str()))); + } +} + diff --git a/apps/opencs/model/tools/search.hpp b/apps/opencs/model/tools/search.hpp new file mode 100644 index 0000000000..c9dfc4c446 --- /dev/null +++ b/apps/opencs/model/tools/search.hpp @@ -0,0 +1,96 @@ +#ifndef CSM_TOOLS_SEARCH_H +#define CSM_TOOLS_SEARCH_H + +#include +#include + +#include +#include + +class QModelIndex; + +namespace CSMDoc +{ + class Messages; + class Document; +} + +namespace CSMWorld +{ + class IdTableBase; + class UniversalId; +} + +namespace CSMTools +{ + class Search + { + public: + + enum Type + { + Type_Text = 0, + Type_TextRegEx = 1, + Type_Id = 2, + Type_IdRegEx = 3, + Type_RecordState = 4, + Type_None + }; + + private: + + Type mType; + std::string mText; + QRegExp mRegExp; + int mValue; + std::set mColumns; + int mIdColumn; + int mTypeColumn; + int mPaddingBefore; + int mPaddingAfter; + + void searchTextCell (const CSMWorld::IdTableBase *model, const QModelIndex& index, + const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const; + + void searchRegExCell (const CSMWorld::IdTableBase *model, const QModelIndex& index, + const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const; + + void searchRecordStateCell (const CSMWorld::IdTableBase *model, + const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, + CSMDoc::Messages& messages) const; + + QString formatDescription (const QString& description, int pos, int length) const; + + QString flatten (const QString& text) const; + + public: + + Search(); + + Search (Type type, const std::string& value); + + Search (Type type, const QRegExp& value); + + Search (Type type, int value); + + // Configure search for the specified model. + void configure (const CSMWorld::IdTableBase *model); + + // Search row in \a model and store results in \a messages. + // + // \attention *this needs to be configured for \a model. + void searchRow (const CSMWorld::IdTableBase *model, int row, + CSMDoc::Messages& messages) const; + + void setPadding (int before, int after); + + // Configuring *this for the model is not necessary when calling this function. + void replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model, + const CSMWorld::UniversalId& id, const std::string& messageHint, + const std::string& replaceText) const; + }; +} + +Q_DECLARE_METATYPE (CSMTools::Search) + +#endif diff --git a/apps/opencs/model/tools/searchoperation.cpp b/apps/opencs/model/tools/searchoperation.cpp new file mode 100644 index 0000000000..4512de5829 --- /dev/null +++ b/apps/opencs/model/tools/searchoperation.cpp @@ -0,0 +1,40 @@ + +#include "searchoperation.hpp" + +#include "../doc/state.hpp" +#include "../doc/document.hpp" + +#include "../world/data.hpp" +#include "../world/idtablebase.hpp" + +#include "searchstage.hpp" + +CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document) +: CSMDoc::Operation (CSMDoc::State_Searching, false) +{ + std::vector types = CSMWorld::UniversalId::listTypes ( + CSMWorld::UniversalId::Class_RecordList | + CSMWorld::UniversalId::Class_ResourceList + ); + + for (std::vector::const_iterator iter (types.begin()); + iter!=types.end(); ++iter) + appendStage (new SearchStage (&dynamic_cast ( + *document.getData().getTableModel (*iter)))); +} + +void CSMTools::SearchOperation::configure (const Search& search) +{ + mSearch = search; +} + +void CSMTools::SearchOperation::appendStage (SearchStage *stage) +{ + CSMDoc::Operation::appendStage (stage); + stage->setOperation (this); +} + +const CSMTools::Search& CSMTools::SearchOperation::getSearch() const +{ + return mSearch; +} diff --git a/apps/opencs/model/tools/searchoperation.hpp b/apps/opencs/model/tools/searchoperation.hpp new file mode 100644 index 0000000000..fbbb388981 --- /dev/null +++ b/apps/opencs/model/tools/searchoperation.hpp @@ -0,0 +1,38 @@ +#ifndef CSM_TOOLS_SEARCHOPERATION_H +#define CSM_TOOLS_SEARCHOPERATION_H + +#include "../doc/operation.hpp" + +#include "search.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSMTools +{ + class SearchStage; + + class SearchOperation : public CSMDoc::Operation + { + Search mSearch; + + public: + + SearchOperation (CSMDoc::Document& document); + + /// \attention Do not call this function while a search is running. + void configure (const Search& search); + + void appendStage (SearchStage *stage); + ///< The ownership of \a stage is transferred to *this. + /// + /// \attention Do no call this function while this Operation is running. + + const Search& getSearch() const; + + }; +} + +#endif diff --git a/apps/opencs/model/tools/searchstage.cpp b/apps/opencs/model/tools/searchstage.cpp new file mode 100644 index 0000000000..17859d9309 --- /dev/null +++ b/apps/opencs/model/tools/searchstage.cpp @@ -0,0 +1,30 @@ + +#include "searchstage.hpp" + +#include "../world/idtablebase.hpp" + +#include "searchoperation.hpp" + +CSMTools::SearchStage::SearchStage (const CSMWorld::IdTableBase *model) +: mModel (model), mOperation (0) +{} + +int CSMTools::SearchStage::setup() +{ + if (mOperation) + mSearch = mOperation->getSearch(); + + mSearch.configure (mModel); + + return mModel->rowCount(); +} + +void CSMTools::SearchStage::perform (int stage, CSMDoc::Messages& messages) +{ + mSearch.searchRow (mModel, stage, messages); +} + +void CSMTools::SearchStage::setOperation (const SearchOperation *operation) +{ + mOperation = operation; +} diff --git a/apps/opencs/model/tools/searchstage.hpp b/apps/opencs/model/tools/searchstage.hpp new file mode 100644 index 0000000000..073487c0d2 --- /dev/null +++ b/apps/opencs/model/tools/searchstage.hpp @@ -0,0 +1,37 @@ +#ifndef CSM_TOOLS_SEARCHSTAGE_H +#define CSM_TOOLS_SEARCHSTAGE_H + +#include "../doc/stage.hpp" + +#include "search.hpp" + +namespace CSMWorld +{ + class IdTableBase; +} + +namespace CSMTools +{ + class SearchOperation; + + class SearchStage : public CSMDoc::Stage + { + const CSMWorld::IdTableBase *mModel; + Search mSearch; + const SearchOperation *mOperation; + + public: + + SearchStage (const CSMWorld::IdTableBase *model); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + + void setOperation (const SearchOperation *operation); + }; +} + +#endif diff --git a/apps/opencs/model/tools/skillcheck.cpp b/apps/opencs/model/tools/skillcheck.cpp index e061e042cc..2b55526e09 100644 --- a/apps/opencs/model/tools/skillcheck.cpp +++ b/apps/opencs/model/tools/skillcheck.cpp @@ -39,4 +39,4 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages) if (skill.mDescription.empty()) messages.push_back (std::make_pair (id, skill.mId + " has an empty description")); -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp index e122ced915..f78932a32b 100644 --- a/apps/opencs/model/tools/soundcheck.cpp +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -31,4 +31,4 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages) messages.push_back (std::make_pair (id, "Maximum range larger than minimum range")); /// \todo check, if the sound file exists -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/spellcheck.cpp b/apps/opencs/model/tools/spellcheck.cpp index 0b59dc862a..bd076d2a5a 100644 --- a/apps/opencs/model/tools/spellcheck.cpp +++ b/apps/opencs/model/tools/spellcheck.cpp @@ -37,4 +37,4 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages) messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs")); /// \todo check data members that can't be edited in the table view -} \ No newline at end of file +} diff --git a/apps/opencs/model/tools/startscriptcheck.cpp b/apps/opencs/model/tools/startscriptcheck.cpp new file mode 100644 index 0000000000..e3c01368bd --- /dev/null +++ b/apps/opencs/model/tools/startscriptcheck.cpp @@ -0,0 +1,31 @@ + +#include "startscriptcheck.hpp" + +#include + +CSMTools::StartScriptCheckStage::StartScriptCheckStage ( + const CSMWorld::IdCollection& startScripts, + const CSMWorld::IdCollection& scripts) +: mStartScripts (startScripts), mScripts (scripts) +{} + +void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages) +{ + const CSMWorld::Record& record = mStartScripts.getRecord (stage); + + if (record.isDeleted()) + return; + + std::string scriptId = record.get().mId; + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_StartScript, scriptId); + + if (mScripts.searchId (Misc::StringUtils::lowerCase (scriptId))==-1) + messages.push_back ( + std::make_pair (id, "Start script " + scriptId + " does not exist")); +} + +int CSMTools::StartScriptCheckStage::setup() +{ + return mStartScripts.getSize(); +} diff --git a/apps/opencs/model/tools/startscriptcheck.hpp b/apps/opencs/model/tools/startscriptcheck.hpp new file mode 100644 index 0000000000..cb82cbae7d --- /dev/null +++ b/apps/opencs/model/tools/startscriptcheck.hpp @@ -0,0 +1,28 @@ +#ifndef CSM_TOOLS_STARTSCRIPTCHECK_H +#define CSM_TOOLS_STARTSCRIPTCHECK_H + +#include +#include + +#include "../doc/stage.hpp" + +#include "../world/idcollection.hpp" + +namespace CSMTools +{ + class StartScriptCheckStage : public CSMDoc::Stage + { + const CSMWorld::IdCollection& mStartScripts; + const CSMWorld::IdCollection& mScripts; + + public: + + StartScriptCheckStage (const CSMWorld::IdCollection& startScripts, + const CSMWorld::IdCollection& scripts); + + virtual void perform(int stage, CSMDoc::Messages& messages); + virtual int setup(); + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index e78758bb67..970a8ac4fe 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -24,31 +24,34 @@ #include "scriptcheck.hpp" #include "bodypartcheck.hpp" #include "referencecheck.hpp" +#include "startscriptcheck.hpp" +#include "searchoperation.hpp" -CSMDoc::Operation *CSMTools::Tools::get (int type) +CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { switch (type) { - case CSMDoc::State_Verifying: return mVerifier; + case CSMDoc::State_Verifying: return &mVerifier; + case CSMDoc::State_Searching: return &mSearch; } return 0; } -const CSMDoc::Operation *CSMTools::Tools::get (int type) const +const CSMDoc::OperationHolder *CSMTools::Tools::get (int type) const { return const_cast (this)->get (type); } -CSMDoc::Operation *CSMTools::Tools::getVerifier() +CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() { - if (!mVerifier) + if (!mVerifierOperation) { - mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false); + mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false); - connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); - connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); - connect (mVerifier, + connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); + connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); + connect (&mVerifier, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); @@ -59,54 +62,75 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() mandatoryIds.push_back ("Month"); mandatoryIds.push_back ("PCRace"); - mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), + mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(), CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); - mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); + mVerifierOperation->appendStage (new SkillCheckStage (mData.getSkills())); - mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); + mVerifierOperation->appendStage (new ClassCheckStage (mData.getClasses())); - mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); + mVerifierOperation->appendStage (new FactionCheckStage (mData.getFactions())); - mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); + mVerifierOperation->appendStage (new RaceCheckStage (mData.getRaces())); - mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); + mVerifierOperation->appendStage (new SoundCheckStage (mData.getSounds())); - mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); + mVerifierOperation->appendStage (new RegionCheckStage (mData.getRegions())); - mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); + mVerifierOperation->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); - mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); + mVerifierOperation->appendStage (new SpellCheckStage (mData.getSpells())); - mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); + mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); - mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions())); + mVerifierOperation->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions())); - mVerifier->appendStage (new ScriptCheckStage (mDocument)); + mVerifierOperation->appendStage (new ScriptCheckStage (mDocument)); - mVerifier->appendStage( + mVerifierOperation->appendStage (new StartScriptCheckStage (mData.getStartScripts(), mData.getScripts())); + + mVerifierOperation->appendStage( new BodyPartCheckStage( mData.getBodyParts(), mData.getResources( CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), mData.getRaces() )); + + mVerifier.setOperation (mVerifierOperation); } - return mVerifier; + return &mVerifier; } CSMTools::Tools::Tools (CSMDoc::Document& document) -: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) +: mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0), + mSearchOperation (0) { // index 0: load error log mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0)); + + connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); + connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); + connect (&mSearch, + SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), + this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); } CSMTools::Tools::~Tools() { - delete mVerifier; + if (mVerifierOperation) + { + mVerifier.abortAndWait(); + delete mVerifierOperation; + } + if (mSearchOperation) + { + mSearch.abortAndWait(); + delete mSearchOperation; + } + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) delete iter->second; } @@ -121,9 +145,31 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier() return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); } +CSMWorld::UniversalId CSMTools::Tools::newSearch() +{ + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true))); + + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1); +} + +void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Search& search) +{ + mActiveReports[CSMDoc::State_Searching] = searchId.getIndex(); + + if (!mSearchOperation) + { + mSearchOperation = new SearchOperation (mDocument); + mSearch.setOperation (mSearchOperation); + } + + mSearchOperation->configure (search); + + mSearch.start(); +} + void CSMTools::Tools::abortOperation (int type) { - if (CSMDoc::Operation *operation = get (type)) + if (CSMDoc::OperationHolder *operation = get (type)) operation->abort(); } @@ -132,13 +178,14 @@ int CSMTools::Tools::getRunningOperations() const static const int sOperations[] = { CSMDoc::State_Verifying, + CSMDoc::State_Searching, -1 }; int result = 0; for (int i=0; sOperations[i]!=-1; ++i) - if (const CSMDoc::Operation *operation = get (sOperations[i])) + if (const CSMDoc::OperationHolder *operation = get (sOperations[i])) if (operation->isRunning()) result |= sOperations[i]; @@ -148,9 +195,10 @@ int CSMTools::Tools::getRunningOperations() const CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) { if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults && - id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog) + id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog && + id.getType()!=CSMWorld::UniversalId::Type_Search) throw std::logic_error ("invalid request for report model: " + id.toString()); - + return mReports.at (id.getIndex()); } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 5125a36381..0f9e570445 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -5,6 +5,8 @@ #include +#include "../doc/operationholder.hpp" + namespace CSMWorld { class Data; @@ -20,6 +22,8 @@ namespace CSMDoc namespace CSMTools { class ReportModel; + class Search; + class SearchOperation; class Tools : public QObject { @@ -27,7 +31,10 @@ namespace CSMTools CSMDoc::Document& mDocument; CSMWorld::Data& mData; - CSMDoc::Operation *mVerifier; + CSMDoc::Operation *mVerifierOperation; + CSMDoc::OperationHolder mVerifier; + SearchOperation *mSearchOperation; + CSMDoc::OperationHolder mSearch; std::map mReports; int mNextReportNumber; std::map mActiveReports; // type, report number @@ -36,12 +43,12 @@ namespace CSMTools Tools (const Tools&); Tools& operator= (const Tools&); - CSMDoc::Operation *getVerifier(); + CSMDoc::OperationHolder *getVerifier(); - CSMDoc::Operation *get (int type); + CSMDoc::OperationHolder *get (int type); ///< Returns a 0-pointer, if operation hasn't been used yet. - const CSMDoc::Operation *get (int type) const; + const CSMDoc::OperationHolder *get (int type) const; ///< Returns a 0-pointer, if operation hasn't been used yet. public: @@ -53,6 +60,11 @@ namespace CSMTools CSMWorld::UniversalId runVerifier(); ///< \return ID of the report for this verification run + /// Return ID of the report for this search. + CSMWorld::UniversalId newSearch(); + + void runSearch (const CSMWorld::UniversalId& searchId, const Search& search); + void abortOperation (int type); ///< \attention The operation is not aborted immediately. diff --git a/apps/opencs/model/world/cell.hpp b/apps/opencs/model/world/cell.hpp index a47dbf45df..f393e2cf97 100644 --- a/apps/opencs/model/world/cell.hpp +++ b/apps/opencs/model/world/cell.hpp @@ -21,4 +21,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/collectionbase.cpp b/apps/opencs/model/world/collectionbase.cpp index 241f198cb2..b8eed4192d 100644 --- a/apps/opencs/model/world/collectionbase.cpp +++ b/apps/opencs/model/world/collectionbase.cpp @@ -28,4 +28,4 @@ int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const throw std::logic_error ("invalid column index"); return index; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/collectionbase.hpp b/apps/opencs/model/world/collectionbase.hpp index 442055d5f3..ef826e31c8 100644 --- a/apps/opencs/model/world/collectionbase.hpp +++ b/apps/opencs/model/world/collectionbase.hpp @@ -106,4 +106,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index f6363fe2eb..17e4def2fc 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -19,7 +19,80 @@ std::string CSMWorld::ColumnBase::getTitle() const return Columns::getName (static_cast (mColumnId)); } -int CSMWorld::ColumnBase::getId() const +int CSMWorld::ColumnBase::getId() const { return mColumnId; -} \ No newline at end of file +} + +bool CSMWorld::ColumnBase::isId (Display display) +{ + static const Display ids[] = + { + Display_Skill, + Display_Class, + Display_Faction, + Display_Race, + Display_Sound, + Display_Region, + Display_Birthsign, + Display_Spell, + Display_Cell, + Display_Referenceable, + Display_Activator, + Display_Potion, + Display_Apparatus, + Display_Armor, + Display_Book, + Display_Clothing, + Display_Container, + Display_Creature, + Display_Door, + Display_Ingredient, + Display_CreatureLevelledList, + Display_ItemLevelledList, + Display_Light, + Display_Lockpick, + Display_Miscellaneous, + Display_Npc, + Display_Probe, + Display_Repair, + Display_Static, + Display_Weapon, + Display_Reference, + Display_Filter, + Display_Topic, + Display_Journal, + Display_TopicInfo, + Display_JournalInfo, + Display_Scene, + Display_GlobalVariable, + Display_Script, + + Display_Mesh, + Display_Icon, + Display_Music, + Display_SoundRes, + Display_Texture, + Display_Video, + + Display_Id, + + Display_None + }; + + for (int i=0; ids[i]!=Display_None; ++i) + if (ids[i]==display) + return true; + + return false; +} + +bool CSMWorld::ColumnBase::isText (Display display) +{ + return display==Display_String || display==Display_LongString; +} + +bool CSMWorld::ColumnBase::isScript (Display display) +{ + return display==Display_ScriptFile || display==Display_ScriptLines; +} diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index db9b8b3c64..6f67898f66 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -101,9 +101,11 @@ namespace CSMWorld Display_Texture, Display_Video, Display_Colour, + Display_ScriptFile, Display_ScriptLines, // console context Display_SoundGeneratorType, - Display_School + Display_School, + Display_Id }; int mColumnId; @@ -122,6 +124,12 @@ namespace CSMWorld virtual std::string getTitle() const; virtual int getId() const; + + static bool isId (Display display); + + static bool isText (Display display); + + static bool isScript (Display display); }; template diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index da14bb4955..e67fdd59c8 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -43,7 +43,7 @@ namespace CSMWorld struct StringIdColumn : public Column { StringIdColumn (bool hidden = false) - : Column (Columns::ColumnId_Id, ColumnBase::Display_String, + : Column (Columns::ColumnId_Id, ColumnBase::Display_Id, hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue) {} @@ -818,7 +818,7 @@ namespace CSMWorld ScriptColumn (Type type) : Column (Columns::ColumnId_ScriptText, - type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines, + type==Type_File ? ColumnBase::Display_ScriptFile : ColumnBase::Display_ScriptLines, type==Type_File ? 0 : ColumnBase::Flag_Dialogue) {} diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 4e146d87c0..ca6faafbc0 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -264,4 +264,4 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert() if (mExtendedTypes.size()>1) mDocument.getUndoStack().endMacro(); -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index de0e9a4e53..1d86ba0806 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -170,4 +170,4 @@ void CSMWorld::CloneCommand::redo() void CSMWorld::CloneCommand::undo() { mModel.removeRow (mModel.getModelIndex (mId, 0).row()); -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index a15c071a8b..3c24b64a5d 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { class IdTable; class IdTable; - class RecordBase; + struct RecordBase; class ModifyCommand : public QUndoCommand { @@ -141,4 +141,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 67f6822c7c..39cff3db65 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -254,6 +254,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mPathgrids.addColumn (new RecordStateColumn); mPathgrids.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Pathgrid)); + mStartScripts.addColumn (new StringIdColumn); + mStartScripts.addColumn (new RecordStateColumn); + mStartScripts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_StartScript)); + mRefs.addColumn (new StringIdColumn (true)); mRefs.addColumn (new RecordStateColumn); mRefs.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Reference)); @@ -327,6 +331,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen); addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid); + addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript); addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), UniversalId::Type_Referenceable); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); @@ -615,6 +620,16 @@ CSMWorld::SubCellCollection& CSMWorld::Data::getPathgrids() return mPathgrids; } +const CSMWorld::IdCollection& CSMWorld::Data::getStartScripts() const +{ + return mStartScripts; +} + +CSMWorld::IdCollection& CSMWorld::Data::getStartScripts() +{ + return mStartScripts; +} + const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const { return mResourcesManager.get (id.getType()); @@ -719,6 +734,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break; case ESM::REC_MGEF: mMagicEffects.load (*mReader, mBase); break; case ESM::REC_PGRD: mPathgrids.load (*mReader, mBase); break; + case ESM::REC_SSCR: mStartScripts.load (*mReader, mBase); break; case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break; @@ -729,7 +745,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (index!=-1 && !mBase) mLand.getRecord (index).mModified.mLand->loadData ( ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | - ESM::Land::DATA_VTEX); + ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); break; } diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 02f7bc4526..298a9be1fc 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -80,6 +81,7 @@ namespace CSMWorld SubCellCollection mPathgrids; IdCollection mDebugProfiles; IdCollection mSoundGens; + IdCollection mStartScripts; InfoCollection mTopicInfos; InfoCollection mJournalInfos; IdCollection mCells; @@ -225,6 +227,10 @@ namespace CSMWorld SubCellCollection& getPathgrids(); + const IdCollection& getStartScripts() const; + + IdCollection& getStartScripts(); + /// Throws an exception, if \a id does not match a resources list. const Resources& getResources (const UniversalId& id) const; diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 707d7133b8..6f4be71786 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -10,7 +10,7 @@ namespace CSMWorld { class CollectionBase; - class RecordBase; + struct RecordBase; class IdTable : public IdTableBase { @@ -82,7 +82,7 @@ namespace CSMWorld /// Is \a id flagged as deleted? virtual bool isDeleted (const std::string& id) const; - int getColumnId(int column) const; + virtual int getColumnId(int column) const; }; } diff --git a/apps/opencs/model/world/idtablebase.cpp b/apps/opencs/model/world/idtablebase.cpp index 31d8d461e1..389f5396e4 100644 --- a/apps/opencs/model/world/idtablebase.cpp +++ b/apps/opencs/model/world/idtablebase.cpp @@ -6,4 +6,4 @@ CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features unsigned int CSMWorld::IdTableBase::getFeatures() const { return mFeatures; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/idtablebase.hpp b/apps/opencs/model/world/idtablebase.hpp index ef5a9c42ed..0d77d48efc 100644 --- a/apps/opencs/model/world/idtablebase.hpp +++ b/apps/opencs/model/world/idtablebase.hpp @@ -60,6 +60,8 @@ namespace CSMWorld /// Is \a id flagged as deleted? virtual bool isDeleted (const std::string& id) const = 0; + virtual int getColumnId (int column) const = 0; + unsigned int getFeatures() const; }; } diff --git a/apps/opencs/model/world/infocollection.cpp b/apps/opencs/model/world/infocollection.cpp index 50d09f3139..f2d81823cf 100644 --- a/apps/opencs/model/world/infocollection.cpp +++ b/apps/opencs/model/world/infocollection.cpp @@ -26,7 +26,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base) if (!record2.get().mPrev.empty()) { - index = getIndex (record2.get().mPrev, topic); + index = getInfoIndex (record2.get().mPrev, topic); if (index!=-1) ++index; @@ -34,7 +34,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base) if (index==-1 && !record2.get().mNext.empty()) { - index = getIndex (record2.get().mNext, topic); + index = getInfoIndex (record2.get().mNext, topic); } if (index==-1) @@ -60,7 +60,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base) } } -int CSMWorld::InfoCollection::getIndex (const std::string& id, const std::string& topic) const +int CSMWorld::InfoCollection::getInfoIndex (const std::string& id, const std::string& topic) const { std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id; diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index ae61f5d391..6db47373d0 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -6,7 +6,7 @@ namespace ESM { - class Dialogue; + struct Dialogue; } namespace CSMWorld @@ -22,7 +22,7 @@ namespace CSMWorld void load (const Info& record, bool base); - int getIndex (const std::string& id, const std::string& topic) const; + int getInfoIndex (const std::string& id, const std::string& topic) const; ///< Return index for record \a id or -1 (if not present; deleted records are considered) /// /// \param id info ID without topic prefix @@ -47,4 +47,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/pathgrid.hpp b/apps/opencs/model/world/pathgrid.hpp index d8cc89f24f..7e7b7c3bb6 100644 --- a/apps/opencs/model/world/pathgrid.hpp +++ b/apps/opencs/model/world/pathgrid.hpp @@ -26,4 +26,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/record.cpp b/apps/opencs/model/world/record.cpp index 14f63c155d..ef2f4d3202 100644 --- a/apps/opencs/model/world/record.cpp +++ b/apps/opencs/model/world/record.cpp @@ -18,4 +18,4 @@ bool CSMWorld::RecordBase::isErased() const bool CSMWorld::RecordBase::isModified() const { return mState==State_Modified || mState==State_ModifiedOnly; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 861fc47a3b..3362f9f963 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -22,6 +22,8 @@ namespace CSMWorld virtual RecordBase *clone() const = 0; + virtual RecordBase *modifiedCopy() const = 0; + virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. @@ -38,8 +40,15 @@ namespace CSMWorld ESXRecordT mBase; ESXRecordT mModified; + Record(); + + Record(State state, + const ESXRecordT *base = 0, const ESXRecordT *modified = 0); + virtual RecordBase *clone() const; + virtual RecordBase *modifiedCopy() const; + virtual void assign (const RecordBase& record); const ESXRecordT& get() const; @@ -58,6 +67,29 @@ namespace CSMWorld ///< Merge modified into base. }; + template + Record::Record() + : mBase(), mModified() + { } + + template + Record::Record(State state, const ESXRecordT *base, const ESXRecordT *modified) + { + if(base) + mBase = *base; + + if(modified) + mModified = *modified; + + this->mState = state; + } + + template + RecordBase *Record::modifiedCopy() const + { + return new Record (State_ModifiedOnly, 0, &(this->get())); + } + template RecordBase *Record::clone() const { diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index f3c1b0b73f..eee454a168 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -5,4 +5,4 @@ CSMWorld::CellRef::CellRef() { mRefNum.mIndex = 0; mRefNum.mContentFile = 0; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index eb62434cf2..8ab901a6f1 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -5,8 +5,6 @@ namespace CSMWorld { - class Cell; - /// \brief Wrapper for CellRef sub record struct CellRef : public ESM::CellRef { diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 4ecc32b2f9..46572752e3 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -12,7 +12,7 @@ namespace CSMWorld { struct Cell; - struct UniversalId; + class UniversalId; /// \brief References in cells class RefCollection : public Collection diff --git a/apps/opencs/model/world/refidadapter.cpp b/apps/opencs/model/world/refidadapter.cpp index 94ae38c3c2..8f74e61347 100644 --- a/apps/opencs/model/world/refidadapter.cpp +++ b/apps/opencs/model/world/refidadapter.cpp @@ -3,4 +3,4 @@ CSMWorld::RefIdAdapter::RefIdAdapter() {} -CSMWorld::RefIdAdapter::~RefIdAdapter() {} \ No newline at end of file +CSMWorld::RefIdAdapter::~RefIdAdapter() {} diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 0870a2d3e6..74c5dfe584 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -9,7 +9,7 @@ namespace CSMWorld { class RefIdColumn; class RefIdData; - class RecordBase; + struct RecordBase; class RefIdAdapter { @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 034905781d..202b7781c3 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -156,10 +156,16 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mModel.mModel) - record.get().mModel = value.toString().toUtf8().constData(); + record2.mModel = value.toString().toUtf8().constData(); else + { BaseRefIdAdapter::setData (column, data, index, value); + return; + } + + record.setModified(record2); } struct NameColumns : public ModelColumns @@ -216,12 +222,18 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mName.mName) - record.get().mName = value.toString().toUtf8().constData(); + record2.mName = value.toString().toUtf8().constData(); else if (column==mName.mScript) - record.get().mScript = value.toString().toUtf8().constData(); + record2.mScript = value.toString().toUtf8().constData(); else + { ModelRefIdAdapter::setData (column, data, index, value); + return; + } + + record.setModified(record2); } struct InventoryColumns : public NameColumns @@ -283,14 +295,20 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mInventory.mIcon) - record.get().mIcon = value.toString().toUtf8().constData(); + record2.mIcon = value.toString().toUtf8().constData(); else if (column==mInventory.mWeight) - record.get().mData.mWeight = value.toFloat(); + record2.mData.mWeight = value.toFloat(); else if (column==mInventory.mValue) - record.get().mData.mValue = value.toInt(); + record2.mData.mValue = value.toInt(); else + { NameRefIdAdapter::setData (column, data, index, value); + return; + } + + record.setModified(record2); } class PotionRefIdAdapter : public InventoryRefIdAdapter @@ -364,12 +382,18 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mEnchantable.mEnchantment) - record.get().mEnchant = value.toString().toUtf8().constData(); + record2.mEnchant = value.toString().toUtf8().constData(); else if (column==mEnchantable.mEnchantmentPoints) - record.get().mData.mEnchant = value.toInt(); + record2.mData.mEnchant = value.toInt(); else + { InventoryRefIdAdapter::setData (column, data, index, value); + return; + } + + record.setModified(record2); } struct ToolColumns : public InventoryColumns @@ -426,12 +450,18 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mTools.mQuality) - record.get().mData.mQuality = value.toFloat(); + record2.mData.mQuality = value.toFloat(); else if (column==mTools.mUses) - record.get().mData.mUses = value.toInt(); + record2.mData.mUses = value.toInt(); else + { InventoryRefIdAdapter::setData (column, data, index, value); + return; + } + + record.setModified(record2); } struct ActorColumns : public NameColumns @@ -508,16 +538,17 @@ namespace CSMWorld Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); + RecordT record2 = record.get(); if (column==mActors.mHasAi) - record.get().mHasAI = value.toInt(); + record2.mHasAI = value.toInt(); else if (column==mActors.mHello) - record.get().mAiData.mHello = value.toInt(); + record2.mAiData.mHello = value.toInt(); else if (column==mActors.mFlee) - record.get().mAiData.mFlee = value.toInt(); + record2.mAiData.mFlee = value.toInt(); else if (column==mActors.mFight) - record.get().mAiData.mFight = value.toInt(); + record2.mAiData.mFight = value.toInt(); else if (column==mActors.mAlarm) - record.get().mAiData.mAlarm = value.toInt(); + record2.mAiData.mAlarm = value.toInt(); else { typename std::map::const_iterator iter = @@ -525,13 +556,18 @@ namespace CSMWorld if (iter!=mActors.mServices.end()) { if (value.toInt()!=0) - record.get().mAiData.mServices |= iter->second; + record2.mAiData.mServices |= iter->second; else - record.get().mAiData.mServices &= ~iter->second; + record2.mAiData.mServices &= ~iter->second; } else + { NameRefIdAdapter::setData (column, data, index, value); + return; + } } + + record.setModified(record2); } class ApparatusRefIdAdapter : public InventoryRefIdAdapter diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 779d5a40cd..6963c13311 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -40,7 +40,7 @@ CSMWorld::RefIdCollection::RefIdCollection() { BaseColumns baseColumns; - mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_String, + mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_Id, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false)); baseColumns.mId = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState, @@ -470,8 +470,7 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin, const std::string& destination, const CSMWorld::UniversalId::Type type) { - std::auto_ptr newRecord(mData.getRecord(mData.searchId(origin)).clone()); - newRecord->mState = RecordBase::State_ModifiedOnly; + std::auto_ptr newRecord(mData.getRecord(mData.searchId(origin)).modifiedCopy()); mAdapters.find(type)->second->setId(*newRecord, destination); mData.insertRecord(*newRecord, type, destination); } diff --git a/apps/opencs/model/world/regionmap.cpp b/apps/opencs/model/world/regionmap.cpp index 5f030bb52e..f63426c04a 100644 --- a/apps/opencs/model/world/regionmap.cpp +++ b/apps/opencs/model/world/regionmap.cpp @@ -503,4 +503,4 @@ void CSMWorld::RegionMap::cellsChanged (const QModelIndex& topLeft, const QModel // columns we are interested in. If not we can exit the function here and avoid all updating. addCells (topLeft.row(), bottomRight.row()); -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index 13c8df84d1..8c94398906 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -105,4 +105,4 @@ int CSMWorld::Resources::searchId (const std::string& id) const CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const { return mType; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/resourcesmanager.cpp b/apps/opencs/model/world/resourcesmanager.cpp index 50014f4b5c..deddd83b5e 100644 --- a/apps/opencs/model/world/resourcesmanager.cpp +++ b/apps/opencs/model/world/resourcesmanager.cpp @@ -30,4 +30,4 @@ const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type ty throw std::logic_error ("Unknown resource type"); return iter->second; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/resourcesmanager.hpp b/apps/opencs/model/world/resourcesmanager.hpp index 77f210c478..18861a6a5a 100644 --- a/apps/opencs/model/world/resourcesmanager.hpp +++ b/apps/opencs/model/world/resourcesmanager.hpp @@ -25,4 +25,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/resourcetable.cpp b/apps/opencs/model/world/resourcetable.cpp index a7180434af..2cd44781ab 100644 --- a/apps/opencs/model/world/resourcetable.cpp +++ b/apps/opencs/model/world/resourcetable.cpp @@ -60,7 +60,7 @@ QVariant CSMWorld::ResourceTable::headerData (int section, Qt::Orientation orien return Columns::getName (Columns::ColumnId_Id).c_str(); if (role==ColumnBase::Role_Display) - return ColumnBase::Display_String; + return ColumnBase::Display_Id; break; @@ -143,4 +143,15 @@ std::pair CSMWorld::ResourceTable::view (int bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const { return false; -} \ No newline at end of file +} + +int CSMWorld::ResourceTable::getColumnId (int column) const +{ + switch (column) + { + case 0: return Columns::ColumnId_Id; + case 1: return Columns::ColumnId_RecordType; + } + + return -1; +} diff --git a/apps/opencs/model/world/resourcetable.hpp b/apps/opencs/model/world/resourcetable.hpp index f5011ab2bd..88dcc24b0c 100644 --- a/apps/opencs/model/world/resourcetable.hpp +++ b/apps/opencs/model/world/resourcetable.hpp @@ -51,6 +51,8 @@ namespace CSMWorld /// Is \a id flagged as deleted? virtual bool isDeleted (const std::string& id) const; + + virtual int getColumnId (int column) const; }; } diff --git a/apps/opencs/model/world/scope.cpp b/apps/opencs/model/world/scope.cpp index e3ebf5ebd1..6e4ce4c027 100644 --- a/apps/opencs/model/world/scope.cpp +++ b/apps/opencs/model/world/scope.cpp @@ -22,4 +22,4 @@ CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id) return Scope_Session; return Scope_Content; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/scriptcontext.cpp b/apps/opencs/model/world/scriptcontext.cpp index 0d2b9984ea..a8c2c94526 100644 --- a/apps/opencs/model/world/scriptcontext.cpp +++ b/apps/opencs/model/world/scriptcontext.cpp @@ -120,4 +120,4 @@ void CSMWorld::ScriptContext::clear() mIds.clear(); mIdsUpdated = false; mLocals.clear(); -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index d19959d44d..fbc942f8e2 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -55,6 +55,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; @@ -118,6 +119,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; @@ -126,6 +128,7 @@ namespace { { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; } @@ -345,6 +348,25 @@ std::vector CSMWorld::UniversalId::listReferenceabl return list; } +std::vector CSMWorld::UniversalId::listTypes (int classes) +{ + std::vector list; + + for (int i=0; sNoArg[i].mName; ++i) + if (sNoArg[i].mClass & classes) + list.push_back (sNoArg[i].mType); + + for (int i=0; sIdArg[i].mName; ++i) + if (sIdArg[i].mClass & classes) + list.push_back (sIdArg[i].mType); + + for (int i=0; sIndexArg[i].mName; ++i) + if (sIndexArg[i].mClass & classes) + list.push_back (sIndexArg[i].mType); + + return list; +} + CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type) { for (int i=0; sIdArg[i].mType; ++i) diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index ce2d021d09..0a9fa38473 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -16,16 +16,16 @@ namespace CSMWorld enum Class { Class_None = 0, - Class_Record, - Class_RefRecord, // referenceable record - Class_SubRecord, - Class_RecordList, - Class_Collection, // multiple types of records combined - Class_Transient, // not part of the world data or the project data - Class_NonRecord, // record like data that is not part of the world - Class_Resource, ///< \attention Resource IDs are unique only within the + Class_Record = 1, + Class_RefRecord = 2, // referenceable record + Class_SubRecord = 4, + Class_RecordList = 8, + Class_Collection = 16, // multiple types of records combined + Class_Transient = 32, // not part of the world data or the project data + Class_NonRecord = 64, // record like data that is not part of the world + Class_Resource = 128, ///< \attention Resource IDs are unique only within the /// respective collection - Class_ResourceList + Class_ResourceList = 256 }; enum ArgumentType @@ -128,6 +128,9 @@ namespace CSMWorld Type_MagicEffect, Type_Pathgrids, Type_Pathgrid, + Type_StartScripts, + Type_StartScript, + Type_Search, Type_RunLog }; @@ -178,6 +181,8 @@ namespace CSMWorld static std::vector listReferenceableTypes(); + static std::vector listTypes (int classes); + /// If \a type is a SubRecord, RefRecord or Record type return the type of the table /// that contains records of type \a type. /// Otherwise return Type_None. diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp index 6a72f13ed2..1b3196112d 100644 --- a/apps/opencs/view/doc/filedialog.cpp +++ b/apps/opencs/view/doc/filedialog.cpp @@ -147,17 +147,19 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int) void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool) { - bool success = (mSelector->selectedFiles().size() > 0); + bool success = !mSelector->selectedFiles().empty(); bool isNew = (mAction == ContentAction_New); if (isNew) success = success && !(name.isEmpty()); - else + else if (success) { ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back(); mAdjusterWidget->setName (file->filePath(), !file->isGameFile()); } + else + mAdjusterWidget->setName ("", true); ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success); } diff --git a/apps/opencs/view/doc/globaldebugprofilemenu.cpp b/apps/opencs/view/doc/globaldebugprofilemenu.cpp index 82bd963269..b883813859 100644 --- a/apps/opencs/view/doc/globaldebugprofilemenu.cpp +++ b/apps/opencs/view/doc/globaldebugprofilemenu.cpp @@ -90,4 +90,4 @@ void CSVDoc::GlobalDebugProfileMenu::profileChanged (const QModelIndex& topLeft, void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action) { emit triggered (std::string (action->text().toUtf8().constData())); -} \ No newline at end of file +} diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 046eb5229f..30235d0f5c 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -20,7 +20,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) : mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0) { - setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str()); + setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str())); setMinimumWidth (400); diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 6977d79535..95cbf012d6 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -18,6 +18,7 @@ void CSVDoc::Operation::updateLabel (int threads) { case CSMDoc::State_Saving: name = "saving"; break; case CSMDoc::State_Verifying: name = "verifying"; break; + case CSMDoc::State_Searching: name = "searching"; break; } std::ostringstream stream; diff --git a/apps/opencs/view/doc/runlogsubview.cpp b/apps/opencs/view/doc/runlogsubview.cpp index 68e888e8d8..1293969996 100644 --- a/apps/opencs/view/doc/runlogsubview.cpp +++ b/apps/opencs/view/doc/runlogsubview.cpp @@ -17,4 +17,4 @@ CSVDoc::RunLogSubView::RunLogSubView (const CSMWorld::UniversalId& id, void CSVDoc::RunLogSubView::setEditLock (bool locked) { // ignored since this SubView does not have editing -} \ No newline at end of file +} diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index a399b5b5bf..df1e7ee492 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -26,7 +26,7 @@ void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &) void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) { mUniversalId = id; - setWindowTitle (mUniversalId.toString().c_str()); + setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str())); } void CSVDoc::SubView::closeEvent (QCloseEvent *event) diff --git a/apps/opencs/view/doc/subviewfactory.cpp b/apps/opencs/view/doc/subviewfactory.cpp index 8576f6b1d1..3137f7e324 100644 --- a/apps/opencs/view/doc/subviewfactory.cpp +++ b/apps/opencs/view/doc/subviewfactory.cpp @@ -35,4 +35,4 @@ CSVDoc::SubView *CSVDoc::SubViewFactoryManager::makeSubView (const CSMWorld::Uni throw std::runtime_error ("Failed to create a sub view for: " + id.toString()); return iter->second->makeSubView (id, document); -} \ No newline at end of file +} diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp index 059b24fd0f..6701379859 100644 --- a/apps/opencs/view/doc/subviewfactoryimp.hpp +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -48,4 +48,4 @@ namespace CSVDoc } } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 9117a6d034..9b601243c0 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -91,6 +91,10 @@ void CSVDoc::View::setupEditMenu() QAction *userSettings = new QAction (tr ("&Preferences"), this); connect (userSettings, SIGNAL (triggered()), this, SIGNAL (editSettingsRequest())); edit->addAction (userSettings); + + QAction *search = new QAction (tr ("Search"), this); + connect (search, SIGNAL (triggered()), this, SLOT (addSearchSubView())); + edit->addAction (search); } void CSVDoc::View::setupViewMenu() @@ -173,6 +177,10 @@ void CSVDoc::View::setupMechanicsMenu() QAction *effects = new QAction (tr ("Magic Effects"), this); connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView())); mechanics->addAction (effects); + + QAction *startScripts = new QAction (tr ("Start Scripts"), this); + connect (startScripts, SIGNAL (triggered()), this, SLOT (addStartScriptsSubView())); + mechanics->addAction (startScripts); } void CSVDoc::View::setupCharacterMenu() @@ -320,7 +328,7 @@ void CSVDoc::View::updateTitle() if (hideTitle) stream << " - " << mSubViews.at (0)->getTitle(); - setWindowTitle (stream.str().c_str()); + setWindowTitle (QString::fromUtf8(stream.str().c_str())); } void CSVDoc::View::updateSubViewIndicies(SubView *view) @@ -439,7 +447,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { - CSMDoc::State_Saving, CSMDoc::State_Verifying, + CSMDoc::State_Saving, CSMDoc::State_Verifying, CSMDoc::State_Searching, -1 // end marker }; @@ -481,6 +489,8 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin (!isReferenceable && id == sb->getUniversalId())) { sb->setFocus(); + if (!hint.empty()) + sb->useHint (hint); return; } } @@ -511,8 +521,6 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin assert(view); view->setParent(this); mSubViews.append(view); // only after assert - if (!hint.empty()) - view->useHint (hint); int minWidth = userSettings.setting ("window/minimum-width", QString("325")).toInt(); view->setMinimumWidth(minWidth); @@ -534,6 +542,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin this, SLOT (updateSubViewIndicies (SubView *))); view->show(); + + if (!hint.empty()) + view->useHint (hint); } void CSVDoc::View::newView() @@ -716,6 +727,16 @@ void CSVDoc::View::addPathgridSubView() addSubView (CSMWorld::UniversalId::Type_Pathgrids); } +void CSVDoc::View::addStartScriptsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_StartScripts); +} + +void CSVDoc::View::addSearchSubView() +{ + addSubView (mDocument->newSearch()); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 55ea5ee515..32d7159c28 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -215,6 +215,10 @@ namespace CSVDoc void addPathgridSubView(); + void addStartScriptsSubView(); + + void addSearchSubView(); + void toggleShowStatusBar (bool show); void loadErrorLog(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 5f6b6b46a4..9fee260789 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -248,7 +248,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view) QMessageBox messageBox(view); CSMDoc::Document *document = view->getDocument(); - messageBox.setWindowTitle (document->getSavePath().filename().string().c_str()); + messageBox.setWindowTitle (QString::fromUtf8(document->getSavePath().filename().string().c_str())); messageBox.setText ("The document has been modified."); messageBox.setInformativeText ("Do you want to save your changes?"); messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 68e99e0dee..bc7f9b5a16 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -193,4 +193,4 @@ std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std:: } return ss.str(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index f4d17510b6..29d12529a4 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -43,4 +43,4 @@ namespace CSVFilter } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 8d97edf47e..d13649d3ee 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -11,6 +11,7 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/data.hpp" +#include "../../model/world/refcollection.hpp" #include "../../model/world/pathgrid.hpp" #include "../world/physicssystem.hpp" @@ -89,26 +90,19 @@ bool CSVRender::Cell::removeObject (const std::string& id) bool CSVRender::Cell::addObjects (int start, int end) { - CSMWorld::IdTable& references = dynamic_cast ( - *mData.getTableModel (CSMWorld::UniversalId::Type_References)); - - int idColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Id); - int cellColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Cell); - int stateColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Modification); - bool modified = false; + const CSMWorld::RefCollection& collection = mData.getReferences(); + for (int i=start; i<=end; ++i) { - std::string cell = Misc::StringUtils::lowerCase (references.data ( - references.index (i, cellColumn)).toString().toUtf8().constData()); + std::string cell = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mCell); - int state = references.data (references.index (i, stateColumn)).toInt(); + CSMWorld::RecordBase::State state = collection.getRecord (i).mState; if (cell==mId && state!=CSMWorld::RecordBase::State_Deleted) { - std::string id = Misc::StringUtils::lowerCase (references.data ( - references.index (i, idColumn)).toString().toUtf8().constData()); + std::string id = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mId); mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false, mPhysics))); modified = true; @@ -138,7 +132,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, if (landIndex != -1) { const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get(); - if(esmLand) + if(esmLand && esmLand->mDataTypes&ESM::Land::DATA_VHGT) { mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true, Terrain::Align_XY)); @@ -159,7 +153,6 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, CSVRender::Cell::~Cell() { -<<<<<<< .mine // destroy manual objects for(std::map, std::string>::iterator iter = mPgEdges.begin(); iter != mPgEdges.end(); ++iter) @@ -181,32 +174,10 @@ CSVRender::Cell::~Cell() delete iter->second; } - mPhysics->removeHeightField(mSceneMgr, mX, mY); -======= if (mTerrain.get()) mPhysics->removeHeightField(mSceneMgr, mX, mY); - - - - - - - - - - - - - - - - - - ->>>>>>> .theirs - for (std::map::iterator iter (mObjects.begin()); iter!=mObjects.end(); ++iter) delete iter->second; diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 51a137d3b3..9361030a30 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -16,4 +16,4 @@ unsigned int CSVRender::EditMode::getInteractionMask() const void CSVRender::EditMode::activate (CSVWidget::SceneToolbar *toolbar) { mWorldspaceWidget->setInteractionMask (mMask); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/lighting.cpp b/apps/opencs/view/render/lighting.cpp index d57570d695..3553ef58cc 100644 --- a/apps/opencs/view/render/lighting.cpp +++ b/apps/opencs/view/render/lighting.cpp @@ -1,4 +1,4 @@ #include "lighting.hpp" -CSVRender::Lighting::~Lighting() {} \ No newline at end of file +CSVRender::Lighting::~Lighting() {} diff --git a/apps/opencs/view/render/lightingbright.cpp b/apps/opencs/view/render/lightingbright.cpp index ab845b924f..a342ab0936 100644 --- a/apps/opencs/view/render/lightingbright.cpp +++ b/apps/opencs/view/render/lightingbright.cpp @@ -27,4 +27,4 @@ void CSVRender::LightingBright::deactivate() } } -void CSVRender::LightingBright::setDefaultAmbient (const Ogre::ColourValue& colour) {} \ No newline at end of file +void CSVRender::LightingBright::setDefaultAmbient (const Ogre::ColourValue& colour) {} diff --git a/apps/opencs/view/render/lightingday.cpp b/apps/opencs/view/render/lightingday.cpp index ab0257c0c7..c5189ccfdf 100644 --- a/apps/opencs/view/render/lightingday.cpp +++ b/apps/opencs/view/render/lightingday.cpp @@ -33,4 +33,4 @@ void CSVRender::LightingDay::deactivate() void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/lightingnight.cpp b/apps/opencs/view/render/lightingnight.cpp index 516bb3f408..7d94dc9646 100644 --- a/apps/opencs/view/render/lightingnight.cpp +++ b/apps/opencs/view/render/lightingnight.cpp @@ -33,4 +33,4 @@ void CSVRender::LightingNight::deactivate() void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour) { mSceneManager->setAmbientLight (colour); -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/navigationorbit.cpp b/apps/opencs/view/render/navigationorbit.cpp index c6e729e967..c5f3eda96f 100644 --- a/apps/opencs/view/render/navigationorbit.cpp +++ b/apps/opencs/view/render/navigationorbit.cpp @@ -97,4 +97,4 @@ bool CSVRender::NavigationOrbit::handleRollKeys (int delta) { mCamera->roll (Ogre::Degree (getFactor (false) * delta)); return true; -} \ No newline at end of file +} diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 4ae63386f8..b4c3f9cda7 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -17,7 +17,7 @@ namespace Ogre namespace CSMWorld { class Data; - class CellRef; + struct CellRef; } namespace CSVWorld diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index df1a5298cd..492874c01b 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -6,7 +6,7 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : CSVDoc::SubView (id) { - setWidget (mTable = new ReportTable (document, id, this)); + setWidget (mTable = new ReportTable (document, id, false, this)); connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)), SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 4cd11925e0..1b07d3c0f6 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -6,11 +6,45 @@ #include #include #include +#include +#include +#include #include "../../model/tools/reportmodel.hpp" #include "../../view/world/idtypedelegate.hpp" +namespace CSVTools +{ + class RichTextDelegate : public QStyledItemDelegate + { + public: + + RichTextDelegate (QObject *parent = 0); + + virtual void paint(QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const; + }; +} + +CSVTools::RichTextDelegate::RichTextDelegate (QObject *parent) : QStyledItemDelegate (parent) +{} + +void CSVTools::RichTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + QTextDocument document; + QVariant value = index.data (Qt::DisplayRole); + if (value.isValid() && !value.isNull()) + { + document.setHtml (value.toString()); + painter->translate (option.rect.topLeft()); + document.drawContents (painter); + painter->translate (-option.rect.topLeft()); + } +} + + void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) { QModelIndexList selectedRows = selectionModel()->selectedRows(); @@ -22,15 +56,32 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) { menu.addAction (mShowAction); menu.addAction (mRemoveAction); - } + bool found = false; + for (QModelIndexList::const_iterator iter (selectedRows.begin()); + iter!=selectedRows.end(); ++iter) + { + QString hint = mModel->data (mModel->index (iter->row(), 2)).toString(); + + if (!hint.isEmpty() && hint[0]=='R') + { + found = true; + break; + } + } + + if (found) + menu.addAction (mReplaceAction); + + } + menu.exec (event->globalPos()); } void CSVTools::ReportTable::mouseMoveEvent (QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) - startDrag (*this); + startDragFromTable (*this); } void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) @@ -67,10 +118,11 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) } CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, - const CSMWorld::UniversalId& id, QWidget *parent) + const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) : CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) { horizontalHeader()->setResizeMode (QHeaderView::Interactive); + horizontalHeader()->setStretchLastSection (true); verticalHeader()->hide(); setSortingEnabled (true); setSelectionBehavior (QAbstractItemView::SelectRows); @@ -84,6 +136,9 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, setItemDelegateForColumn (0, mIdTypeDelegate); + if (richTextDescription) + setItemDelegateForColumn (mModel->columnCount()-1, new RichTextDelegate (this)); + mShowAction = new QAction (tr ("Show"), this); connect (mShowAction, SIGNAL (triggered()), this, SLOT (showSelection())); addAction (mShowAction); @@ -91,6 +146,10 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, mRemoveAction = new QAction (tr ("Remove from list"), this); connect (mRemoveAction, SIGNAL (triggered()), this, SLOT (removeSelection())); addAction (mRemoveAction); + + mReplaceAction = new QAction (tr ("Replace"), this); + connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); + addAction (mReplaceAction); } std::vector CSVTools::ReportTable::getDraggedRecords() const @@ -113,6 +172,42 @@ void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStrin mIdTypeDelegate->updateUserSetting (name, list); } +std::vector CSVTools::ReportTable::getReplaceIndices (bool selection) const +{ + std::vector indices; + + if (selection) + { + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); + ++iter) + { + QString hint = mModel->data (mModel->index (iter->row(), 2)).toString(); + + if (!hint.isEmpty() && hint[0]=='R') + indices.push_back (iter->row()); + } + } + else + { + for (int i=0; irowCount(); ++i) + { + QString hint = mModel->data (mModel->index (i, 2)).toString(); + + if (!hint.isEmpty() && hint[0]=='R') + indices.push_back (i); + } + } + + return indices; +} + +void CSVTools::ReportTable::flagAsReplaced (int index) +{ + mModel->flagAsReplaced (index); +} + void CSVTools::ReportTable::showSelection() { QModelIndexList selectedRows = selectionModel()->selectedRows(); @@ -133,4 +228,9 @@ void CSVTools::ReportTable::removeSelection() mModel->removeRows (iter->row(), 1); selectionModel()->clear(); -} \ No newline at end of file +} + +void CSVTools::ReportTable::clear() +{ + mModel->clear(); +} diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 7a5b232f98..c4d5b414ea 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -25,6 +25,7 @@ namespace CSVTools CSVWorld::CommandDelegate *mIdTypeDelegate; QAction *mShowAction; QAction *mRemoveAction; + QAction *mReplaceAction; private: @@ -36,13 +37,23 @@ namespace CSVTools public: + /// \param richTextDescription Use rich text in the description column. ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id, - QWidget *parent = 0); + bool richTextDescription, QWidget *parent = 0); virtual std::vector getDraggedRecords() const; void updateUserSetting (const QString& name, const QStringList& list); + void clear(); + + // Return indices of rows that are suitable for replacement. + // + // \param selection Only list selected rows. + std::vector getReplaceIndices (bool selection) const; + + void flagAsReplaced (int index); + private slots: void showSelection(); @@ -52,6 +63,8 @@ namespace CSVTools signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); + + void replaceRequest(); }; } diff --git a/apps/opencs/view/tools/searchbox.cpp b/apps/opencs/view/tools/searchbox.cpp new file mode 100644 index 0000000000..ca55207875 --- /dev/null +++ b/apps/opencs/view/tools/searchbox.cpp @@ -0,0 +1,192 @@ + +#include "searchbox.hpp" + +#include + +#include +#include +#include + +#include "../../model/world/columns.hpp" + +#include "../../model/tools/search.hpp" + +void CSVTools::SearchBox::updateSearchButton() +{ + if (!mSearchEnabled) + mSearch.setEnabled (false); + else + { + switch (mMode.currentIndex()) + { + case 0: + case 1: + case 2: + case 3: + + mSearch.setEnabled (!mText.text().isEmpty()); + break; + + case 4: + + mSearch.setEnabled (true); + break; + } + } +} + +CSVTools::SearchBox::SearchBox (QWidget *parent) +: QWidget (parent), mSearch ("Search"), mSearchEnabled (false), mReplace ("Replace All") +{ + mLayout = new QGridLayout (this); + + // search panel + std::vector states = + CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification); + states.resize (states.size()-1); // ignore erased state + + for (std::vector::const_iterator iter (states.begin()); iter!=states.end(); + ++iter) + mRecordState.addItem (QString::fromUtf8 (iter->c_str())); + + mMode.addItem ("Text"); + mMode.addItem ("Text (RegEx)"); + mMode.addItem ("ID"); + mMode.addItem ("ID (RegEx)"); + mMode.addItem ("Record State"); + + mLayout->addWidget (&mMode, 0, 0); + + mLayout->addWidget (&mSearch, 0, 3); + + mInput.insertWidget (0, &mText); + mInput.insertWidget (1, &mRecordState); + + mLayout->addWidget (&mInput, 0, 1); + + connect (&mMode, SIGNAL (activated (int)), this, SLOT (modeSelected (int))); + + connect (&mText, SIGNAL (textChanged (const QString&)), + this, SLOT (textChanged (const QString&))); + + connect (&mSearch, SIGNAL (clicked (bool)), this, SLOT (startSearch (bool))); + + connect (&mText, SIGNAL (returnPressed()), this, SLOT (startSearch())); + + // replace panel + mReplaceInput.insertWidget (0, &mReplaceText); + mReplaceInput.insertWidget (1, &mReplacePlaceholder); + + mLayout->addWidget (&mReplaceInput, 1, 1); + + mLayout->addWidget (&mReplace, 1, 3); + + // layout adjustments + mLayout->setColumnMinimumWidth (2, 50); + mLayout->setColumnStretch (1, 1); + + mLayout->setContentsMargins (0, 0, 0, 0); + + connect (&mReplace, (SIGNAL (clicked (bool))), this, SLOT (replaceAll (bool))); + + // update + modeSelected (0); + + updateSearchButton(); +} + +void CSVTools::SearchBox::setSearchMode (bool enabled) +{ + mSearchEnabled = enabled; + updateSearchButton(); +} + +CSMTools::Search CSVTools::SearchBox::getSearch() const +{ + CSMTools::Search::Type type = static_cast (mMode.currentIndex()); + + switch (type) + { + case CSMTools::Search::Type_Text: + case CSMTools::Search::Type_Id: + + return CSMTools::Search (type, std::string (mText.text().toUtf8().data())); + + case CSMTools::Search::Type_TextRegEx: + case CSMTools::Search::Type_IdRegEx: + + return CSMTools::Search (type, QRegExp (mText.text().toUtf8().data(), Qt::CaseInsensitive)); + + case CSMTools::Search::Type_RecordState: + + return CSMTools::Search (type, mRecordState.currentIndex()); + + case CSMTools::Search::Type_None: + + break; + } + + throw std::logic_error ("invalid search mode index"); +} + +std::string CSVTools::SearchBox::getReplaceText() const +{ + CSMTools::Search::Type type = static_cast (mMode.currentIndex()); + + switch (type) + { + case CSMTools::Search::Type_Text: + case CSMTools::Search::Type_TextRegEx: + case CSMTools::Search::Type_Id: + case CSMTools::Search::Type_IdRegEx: + + return mReplaceText.text().toUtf8().data(); + + default: + + throw std::logic_error ("Invalid search mode for replace"); + } +} + +void CSVTools::SearchBox::setEditLock (bool locked) +{ + mReplace.setEnabled (!locked); +} + +void CSVTools::SearchBox::modeSelected (int index) +{ + switch (index) + { + case CSMTools::Search::Type_Text: + case CSMTools::Search::Type_TextRegEx: + case CSMTools::Search::Type_Id: + case CSMTools::Search::Type_IdRegEx: + + mInput.setCurrentIndex (0); + mReplaceInput.setCurrentIndex (0); + break; + + case CSMTools::Search::Type_RecordState: + mInput.setCurrentIndex (1); + mReplaceInput.setCurrentIndex (1); + break; + } + + updateSearchButton(); +} + +void CSVTools::SearchBox::textChanged (const QString& text) +{ + updateSearchButton(); +} + +void CSVTools::SearchBox::startSearch (bool checked) +{ + if (mSearch.isEnabled()) + emit startSearch (getSearch()); +} + +void CSVTools::SearchBox::replaceAll (bool checked) +{ + emit replaceAll(); +} diff --git a/apps/opencs/view/tools/searchbox.hpp b/apps/opencs/view/tools/searchbox.hpp new file mode 100644 index 0000000000..433c096936 --- /dev/null +++ b/apps/opencs/view/tools/searchbox.hpp @@ -0,0 +1,70 @@ +#ifndef CSV_TOOLS_SEARCHBOX_H +#define CSV_TOOLS_SEARCHBOX_H + +#include +#include +#include +#include +#include +#include + +class QGridLayout; + +namespace CSMTools +{ + class Search; +} + +namespace CSVTools +{ + class SearchBox : public QWidget + { + Q_OBJECT + + QStackedWidget mInput; + QLineEdit mText; + QComboBox mRecordState; + QPushButton mSearch; + QGridLayout *mLayout; + QComboBox mMode; + bool mSearchEnabled; + QStackedWidget mReplaceInput; + QLineEdit mReplaceText; + QLabel mReplacePlaceholder; + QPushButton mReplace; + + private: + + void updateSearchButton(); + + public: + + SearchBox (QWidget *parent = 0); + + void setSearchMode (bool enabled); + + CSMTools::Search getSearch() const; + + std::string getReplaceText() const; + + void setEditLock (bool locked); + + private slots: + + void modeSelected (int index); + + void textChanged (const QString& text); + + void startSearch (bool checked = true); + + void replaceAll (bool checked); + + signals: + + void startSearch (const CSMTools::Search& search); + + void replaceAll(); + }; +} + +#endif diff --git a/apps/opencs/view/tools/searchsubview.cpp b/apps/opencs/view/tools/searchsubview.cpp new file mode 100644 index 0000000000..5743ad7614 --- /dev/null +++ b/apps/opencs/view/tools/searchsubview.cpp @@ -0,0 +1,119 @@ + +#include "searchsubview.hpp" + +#include + +#include "../../model/doc/document.hpp" +#include "../../model/tools/search.hpp" +#include "../../model/tools/reportmodel.hpp" +#include "../../model/world/idtablebase.hpp" + +#include "reporttable.hpp" +#include "searchbox.hpp" + +void CSVTools::SearchSubView::replace (bool selection) +{ + if (mLocked) + return; + + std::vector indices = mTable->getReplaceIndices (selection); + + std::string replace = mSearchBox.getReplaceText(); + + const CSMTools::ReportModel& model = + dynamic_cast (*mTable->model()); + + // We are running through the indices in reverse order to avoid messing up multiple results + // in a single string. + for (std::vector::const_reverse_iterator iter (indices.rbegin()); iter!=indices.rend(); ++iter) + { + CSMWorld::UniversalId id = model.getUniversalId (*iter); + + CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::getParentType (id.getType()); + + CSMWorld::IdTableBase *table = &dynamic_cast ( + *mDocument.getData().getTableModel (type)); + + std::string hint = model.getHint (*iter); + + mSearch.replace (mDocument, table, id, hint, replace); + mTable->flagAsReplaced (*iter); + } +} + +CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) +: CSVDoc::SubView (id), mDocument (document), mPaddingBefore (10), mPaddingAfter (10), + mLocked (false) +{ + QVBoxLayout *layout = new QVBoxLayout; + + layout->setContentsMargins (QMargins (0, 0, 0, 0)); + + layout->addWidget (&mSearchBox); + + layout->addWidget (mTable = new ReportTable (document, id, true), 2); + + QWidget *widget = new QWidget; + + widget->setLayout (layout); + + setWidget (widget); + + stateChanged (document.getState(), &document); + + connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)), + SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); + + connect (mTable, SIGNAL (replaceRequest()), this, SLOT (replaceRequest())); + + connect (&document, SIGNAL (stateChanged (int, CSMDoc::Document *)), + this, SLOT (stateChanged (int, CSMDoc::Document *))); + + connect (&mSearchBox, SIGNAL (startSearch (const CSMTools::Search&)), + this, SLOT (startSearch (const CSMTools::Search&))); + + connect (&mSearchBox, SIGNAL (replaceAll()), this, SLOT (replaceAllRequest())); +} + +void CSVTools::SearchSubView::setEditLock (bool locked) +{ + mLocked = locked; + mSearchBox.setEditLock (locked); +} + +void CSVTools::SearchSubView::updateUserSetting (const QString &name, const QStringList &list) +{ + mTable->updateUserSetting (name, list); + + if (!list.empty()) + { + if (name=="search/char-before") + mPaddingBefore = list.at (0).toInt(); + else if (name=="search/char-after") + mPaddingAfter = list.at (0).toInt(); + } +} + +void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *document) +{ + mSearchBox.setSearchMode (!(state & CSMDoc::State_Searching)); +} + +void CSVTools::SearchSubView::startSearch (const CSMTools::Search& search) +{ + mSearch = search; + mSearch.setPadding (mPaddingBefore, mPaddingAfter); + + mTable->clear(); + mDocument.runSearch (getUniversalId(), mSearch); +} + +void CSVTools::SearchSubView::replaceRequest() +{ + replace (true); +} + +void CSVTools::SearchSubView::replaceAllRequest() +{ + replace (false); +} diff --git a/apps/opencs/view/tools/searchsubview.hpp b/apps/opencs/view/tools/searchsubview.hpp new file mode 100644 index 0000000000..eeefa9afbf --- /dev/null +++ b/apps/opencs/view/tools/searchsubview.hpp @@ -0,0 +1,58 @@ +#ifndef CSV_TOOLS_SEARCHSUBVIEW_H +#define CSV_TOOLS_SEARCHSUBVIEW_H + +#include "../../model/tools/search.hpp" + +#include "../doc/subview.hpp" + +#include "searchbox.hpp" + +class QTableView; +class QModelIndex; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVTools +{ + class ReportTable; + + class SearchSubView : public CSVDoc::SubView + { + Q_OBJECT + + ReportTable *mTable; + SearchBox mSearchBox; + CSMDoc::Document& mDocument; + int mPaddingBefore; + int mPaddingAfter; + CSMTools::Search mSearch; + bool mLocked; + + private: + + void replace (bool selection); + + public: + + SearchSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + + virtual void setEditLock (bool locked); + + virtual void updateUserSetting (const QString &, const QStringList &); + + private slots: + + void stateChanged (int state, CSMDoc::Document *document); + + void startSearch (const CSMTools::Search& search); + + void replaceRequest(); + + void replaceAllRequest(); + }; +} + +#endif diff --git a/apps/opencs/view/tools/subviews.cpp b/apps/opencs/view/tools/subviews.cpp index 8b04aca504..8a343ebe86 100644 --- a/apps/opencs/view/tools/subviews.cpp +++ b/apps/opencs/view/tools/subviews.cpp @@ -4,6 +4,7 @@ #include "../doc/subviewfactoryimp.hpp" #include "reportsubview.hpp" +#include "searchsubview.hpp" void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -11,4 +12,6 @@ void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactory); manager.add (CSMWorld::UniversalId::Type_LoadErrorLog, new CSVDoc::SubViewFactory); -} \ No newline at end of file + manager.add (CSMWorld::UniversalId::Type_Search, + new CSVDoc::SubViewFactory); +} diff --git a/apps/opencs/view/widget/pushbutton.cpp b/apps/opencs/view/widget/pushbutton.cpp index d4e6007944..1baeb7ca27 100644 --- a/apps/opencs/view/widget/pushbutton.cpp +++ b/apps/opencs/view/widget/pushbutton.cpp @@ -106,4 +106,4 @@ CSVWidget::PushButton::Type CSVWidget::PushButton::getType() const void CSVWidget::PushButton::checkedStateChanged (bool checked) { setExtendedToolTip(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 8d871cc5f4..39e051c485 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -100,4 +100,4 @@ void CSVWidget::SceneToolMode::selected() emit modeChanged (iter->second); } -} \ No newline at end of file +} diff --git a/apps/opencs/view/widget/scenetoolrun.cpp b/apps/opencs/view/widget/scenetoolrun.cpp index 0c7a4b9f0d..8de334efeb 100644 --- a/apps/opencs/view/widget/scenetoolrun.cpp +++ b/apps/opencs/view/widget/scenetoolrun.cpp @@ -148,4 +148,4 @@ void CSVWidget::SceneToolRun::clicked (const QModelIndex& index) removeProfile (*iter); updatePanel(); } -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp index a24c58e544..2e7c7fe22a 100644 --- a/apps/opencs/view/world/creator.cpp +++ b/apps/opencs/view/world/creator.cpp @@ -19,4 +19,4 @@ CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& da QUndoStack& undoStack, const CSMWorld::UniversalId& id) const { return 0; -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 8e50e87154..7c0422c882 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -101,4 +101,4 @@ namespace CSVWorld } } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/dialoguecreator.cpp b/apps/opencs/view/world/dialoguecreator.cpp index 3523d5e32b..956cd26dfe 100644 --- a/apps/opencs/view/world/dialoguecreator.cpp +++ b/apps/opencs/view/world/dialoguecreator.cpp @@ -32,4 +32,4 @@ CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& QUndoStack& undoStack, const CSMWorld::UniversalId& id) const { return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 8790601ea3..e383f5e9a6 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -39,8 +40,12 @@ QAbstractItemDelegate(parent), mTable(table) {} -void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QModelIndex& index) const +void CSVWorld::NotEditableSubDelegate::setEditorData (QWidget* editor, const QModelIndex& index) const { + QLabel* label = qobject_cast(editor); + if(!label) + return; + QVariant v = index.data(Qt::EditRole); if (!v.isValid()) { @@ -53,16 +58,17 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QMod if (QVariant::String == v.type()) { - editor->setText(v.toString()); - } else //else we are facing enums + label->setText(v.toString()); + } + else //else we are facing enums { int data = v.toInt(); std::vector enumNames (CSMWorld::Columns::getEnums (static_cast (mTable->getColumnId (index.column())))); - editor->setText(QString::fromUtf8(enumNames.at(data).c_str())); + label->setText(QString::fromUtf8(enumNames.at(data).c_str())); } } -void CSVWorld::NotEditableSubDelegate::setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const +void CSVWorld::NotEditableSubDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { //not editable widgets will not save model data } @@ -79,8 +85,7 @@ QSize CSVWorld::NotEditableSubDelegate::sizeHint (const QStyleOptionViewItem& op QWidget* CSVWorld::NotEditableSubDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, - const QModelIndex& index, - CSMWorld::ColumnBase::Display display) const + const QModelIndex& index) const { return new QLabel(parent); } @@ -223,6 +228,11 @@ void CSVWorld::DialogueDelegateDispatcher::setEditorData (QWidget* editor, const } } +void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const +{ + setModelData(editor, model, index, CSMWorld::ColumnBase::Display_None); +} + void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const { std::map::const_iterator delegateIt(mDelegates.find(display)); @@ -257,7 +267,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: QWidget* editor = NULL; if (! (mTable->flags (index) & Qt::ItemIsEditable)) { - return mNotEditableDelegate.createEditor(qobject_cast(mParent), QStyleOptionViewItem(), index, display); + return mNotEditableDelegate.createEditor(qobject_cast(mParent), QStyleOptionViewItem(), index); } std::map::iterator delegateIt(mDelegates.find(display)); @@ -266,6 +276,8 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: editor = delegateIt->second->createEditor(qobject_cast(mParent), QStyleOptionViewItem(), index, display); DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display); + // NOTE: For each entry in CSVWorld::CommandDelegate::createEditor() a corresponding entry + // is required here if (qobject_cast(editor)) { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); @@ -286,10 +298,12 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: { connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited())); } - else if (qobject_cast(editor)) + else if (qobject_cast(editor) || qobject_cast(editor)) { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); } + else // throw an exception because this is a coding error + throw std::logic_error ("Dialogue editor type missing"); connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); mProxys.push_back(proxy); //deleted in the destructor diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 4c260170f3..5bd226960f 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -40,9 +40,9 @@ namespace CSVWorld public: NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent = 0); - virtual void setEditorData (QLabel* editor, const QModelIndex& index) const; + virtual void setEditorData (QWidget* editor, const QModelIndex& index) const; - virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const; + virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; ///< does nothing @@ -52,8 +52,7 @@ namespace CSVWorld virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, - const QModelIndex& index, - CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const; + const QModelIndex& index) const; }; //this can't be nested into the DialogueDelegateDispatcher, because it needs to emit signals @@ -119,6 +118,8 @@ namespace CSVWorld virtual void setEditorData (QWidget* editor, const QModelIndex& index) const; + virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const; virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; @@ -209,4 +210,4 @@ namespace CSVWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index c33fa58ad6..f45c458091 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -3,7 +3,7 @@ #include "../../model/world/tablemimedata.hpp" #include "dragrecordtable.hpp" -void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table) +void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table) { CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument); diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 8c5f1b8418..4996c03acd 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -33,7 +33,7 @@ namespace CSVWorld void setEditLock(bool locked); protected: - void startDrag(const DragRecordTable& table); + void startDragFromTable(const DragRecordTable& table); void dragEnterEvent(QDragEnterEvent *event); diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 168e5cb0a3..7c305b1b6b 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -46,7 +46,6 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QModelIndex& index) const { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None); - //overloading virtual functions is HARD } QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index afa59bc459..b4cf460403 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -276,4 +276,4 @@ void CSVWorld::GenericCreator::scopeChanged (int index) { update(); updateNamespace(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 8c8c34bd81..6780050825 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -111,4 +111,4 @@ namespace CSVWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/idvalidator.cpp b/apps/opencs/view/world/idvalidator.cpp index 7caa20f9b5..13b05d2d17 100644 --- a/apps/opencs/view/world/idvalidator.cpp +++ b/apps/opencs/view/world/idvalidator.cpp @@ -120,4 +120,4 @@ void CSVWorld::IdValidator::setNamespace (const std::string& namespace_) std::string CSVWorld::IdValidator::getError() const { return mError; -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 1d914716ba..14034ea7f4 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -94,4 +94,4 @@ std::string CSVWorld::InfoCreator::getErrors() const void CSVWorld::InfoCreator::topicChanged() { update(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/previewsubview.cpp b/apps/opencs/view/world/previewsubview.cpp index 1ae466f42b..1c2d6b95c7 100644 --- a/apps/opencs/view/world/previewsubview.cpp +++ b/apps/opencs/view/world/previewsubview.cpp @@ -67,4 +67,4 @@ void CSVWorld::PreviewSubView::referenceableIdChanged (const std::string& id) setWindowTitle (QString::fromUtf8 (mTitle.c_str())); emit updateTitle(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 9497e40544..bc96b0952a 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -345,7 +345,7 @@ void CSVWorld::RegionMap::viewInTable() void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) { - startDrag(*this); + startDragFromTable(*this); } std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const @@ -400,7 +400,7 @@ void CSVWorld::RegionMap::dropEvent (QDropEvent* event) QModelIndex index2(cellsModel->getModelIndex (cellId, cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region))); - mDocument.getUndoStack().push(new CSMWorld::ModifyCommand + mDocument.getUndoStack().push(new CSMWorld::ModifyCommand (*cellsModel, index2, QString::fromUtf8(record.getId().c_str()))); mRegionId = record.getId(); diff --git a/apps/opencs/view/world/regionmapsubview.cpp b/apps/opencs/view/world/regionmapsubview.cpp index a7675a4a6d..411e24e754 100644 --- a/apps/opencs/view/world/regionmapsubview.cpp +++ b/apps/opencs/view/world/regionmapsubview.cpp @@ -24,4 +24,4 @@ void CSVWorld::RegionMapSubView::editRequest (const CSMWorld::UniversalId& id, const std::string& hint) { focusId (id, hint); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index c2d94ab5d3..271b0316d3 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -156,4 +156,4 @@ void CSVWorld::ScriptEdit::updateHighlighting() ChangeLock lock (*this); mHighlighter->rehighlight(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index c67385816c..0192bc5503 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -76,4 +76,4 @@ namespace CSVWorld void updateHighlighting(); }; } -#endif // SCRIPTEDIT_H \ No newline at end of file +#endif // SCRIPTEDIT_H diff --git a/apps/opencs/view/world/scripthighlighter.cpp b/apps/opencs/view/world/scripthighlighter.cpp index 36cebcb768..6dda8d4faf 100644 --- a/apps/opencs/view/world/scripthighlighter.cpp +++ b/apps/opencs/view/world/scripthighlighter.cpp @@ -142,4 +142,4 @@ void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text) void CSVWorld::ScriptHighlighter::invalidateIds() { mContext.invalidateIds(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 9b50a61f89..ea9dcee8cd 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -22,7 +22,7 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: for (int i=0; icolumnCount(); ++i) if (mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display)== - CSMWorld::ColumnBase::Display_Script) + CSMWorld::ColumnBase::Display_ScriptFile) { mColumn = i; break; @@ -68,6 +68,7 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint) if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line)) cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column); + mEditor->setFocus(); mEditor->setTextCursor (cursor); } } diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp index 16ffc7b80b..561476577a 100644 --- a/apps/opencs/view/world/scriptsubview.hpp +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -46,4 +46,4 @@ namespace CSVWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index c5d969d0df..cd9b37a645 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -43,6 +43,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_BodyParts, CSMWorld::UniversalId::Type_SoundGens, CSMWorld::UniversalId::Type_Pathgrids, + CSMWorld::UniversalId::Type_StartScripts, CSMWorld::UniversalId::Type_None // end marker }; @@ -123,6 +124,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_BodyPart, CSMWorld::UniversalId::Type_SoundGen, CSMWorld::UniversalId::Type_Pathgrid, + CSMWorld::UniversalId::Type_StartScript, CSMWorld::UniversalId::Type_None // end marker }; @@ -170,4 +172,4 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) //preview manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index e864e4ed26..97a3bc2e31 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -635,7 +635,7 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) { if (event->buttons() & Qt::LeftButton) { - startDrag(*this); + startDragFromTable(*this); } } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index c65e12c609..b0f8a035a1 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -139,6 +139,12 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. } +QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + return createEditor (parent, option, index, CSMWorld::ColumnBase::Display_None); +} + QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const { @@ -152,6 +158,8 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO } } + // NOTE: for each editor type (e.g. QLineEdit) there needs to be a corresponding + // entry in CSVWorld::DialogueDelegateDispatcher::makeEditor() switch (display) { case CSMWorld::ColumnBase::Display_Colour: @@ -228,6 +236,11 @@ bool CSVWorld::CommandDelegate::isEditLocked() const return mEditLock; } +void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const +{ + setEditorData (editor, index, false); +} + void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const { QVariant v = index.data(Qt::EditRole); diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index b4d972bf3f..10011798d5 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -130,10 +130,14 @@ namespace CSVWorld virtual void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + virtual QWidget *createEditor (QWidget *parent, + const QStyleOptionViewItem& option, + const QModelIndex& index) const; + virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index, - CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const; + CSMWorld::ColumnBase::Display display) const; void setEditLock (bool locked); @@ -141,8 +145,9 @@ namespace CSVWorld ///< \return Does column require update? - virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const; + virtual void setEditorData (QWidget *editor, const QModelIndex& index) const; + virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const; public slots: diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index eabbb7577e..a183d172dc 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -7,6 +7,7 @@ set(GAME ) if (ANDROID) + set(GAME ${GAME} android_commandLine.cpp) set(GAME ${GAME} android_main.c) endif() @@ -104,7 +105,6 @@ find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) if (NOT ANDROID) add_executable(openmw - ${OPENMW_LIBS} ${OPENMW_LIBS_HEADER} ${OPENMW_FILES} ${GAME} ${GAME_HEADER} ${APPLE_BUNDLE_RESOURCES} @@ -112,7 +112,6 @@ if (NOT ANDROID) else () add_library(openmw SHARED - ${OPENMW_LIBS} ${OPENMW_LIBS_HEADER} ${OPENMW_FILES} ${GAME} ${GAME_HEADER} ) @@ -120,9 +119,10 @@ endif () # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING # when we change the backend. -include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS}) +include_directories(${SOUND_INPUT_INCLUDES}) target_link_libraries(openmw + ${OENGINE_LIBRARY} ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SHINY_LIBRARIES} diff --git a/apps/openmw/android_commandLine.cpp b/apps/openmw/android_commandLine.cpp new file mode 100644 index 0000000000..ebfff28ca2 --- /dev/null +++ b/apps/openmw/android_commandLine.cpp @@ -0,0 +1,27 @@ +#include "android_commandLine.h" +#include "string.h" + +const char **argvData; +int argcData; + +extern "C" void releaseArgv(); + +void releaseArgv() { + delete[] argvData; +} + +JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env, + jobject obj, jint argc, jobjectArray stringArray) { + jboolean iscopy; + argcData = (int) argc; + argvData = new const char *[argcData + 1]; + argvData[0] = "openmw"; + for (int i = 1; i < argcData + 1; i++) { + jstring string = (jstring) (env)->GetObjectArrayElement(stringArray, + i - 1); + argvData[i] = (env)->GetStringUTFChars(string, &iscopy); + (env)->DeleteLocalRef(string); + } + (env)->DeleteLocalRef(stringArray); +} + diff --git a/apps/openmw/android_commandLine.h b/apps/openmw/android_commandLine.h new file mode 100644 index 0000000000..21d1064c6c --- /dev/null +++ b/apps/openmw/android_commandLine.h @@ -0,0 +1,16 @@ + + +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#ifndef _Included_ui_activity_GameActivity_commandLine +#define _Included_ui_activity_GameActivity_commandLine +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env, jobject obj,jint argcData, jobjectArray stringArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/apps/openmw/android_main.c b/apps/openmw/android_main.c index 76da91c4f6..1b28395199 100644 --- a/apps/openmw/android_main.c +++ b/apps/openmw/android_main.c @@ -1,42 +1,37 @@ - #include "../../SDL_internal.h" #ifdef __ANDROID__ #include "SDL_main.h" - /******************************************************************************* - Functions called by JNI -*******************************************************************************/ + Functions called by JNI + *******************************************************************************/ #include /* Called before to initialize JNI bindings */ - - extern void SDL_Android_Init(JNIEnv* env, jclass cls); +extern int argcData; +extern const char **argvData; +void releaseArgv(); +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) -{ - - SDL_Android_Init(env, cls); - - SDL_SetMainReady(); + SDL_Android_Init(env, cls); - -/* Run the application code! */ - - int status; - char *argv[2]; - argv[0] = SDL_strdup("openmw"); - argv[1] = NULL; - status = main(1, argv); + SDL_SetMainReady(); - /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ - /* exit(status); */ + /* Run the application code! */ - return status; + 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; } #endif /* __ANDROID__ */ diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 669bae60a7..a4bb8c5380 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -10,6 +10,8 @@ #include +#include + #include #include @@ -191,15 +193,13 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mExportFonts(false) , mNewGame (false) { - std::srand ( std::time(NULL) ); + OEngine::Misc::Rng::init(); + std::srand ( static_cast(std::time(NULL)) ); MWClass::registerClasses(); - Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE; + Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK; if(SDL_WasInit(flags) == 0) { - //kindly ask SDL not to trash our OGL context - //might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ? - SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); SDL_SetMainReady(); if(SDL_Init(flags) != 0) { @@ -368,9 +368,29 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) // Create input and UI first to set up a bootstrapping environment for // showing a loading screen and keeping the window responsive while doing so - std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input_v2.xml").string(); + std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input_v3.xml").string(); bool keybinderUserExists = boost::filesystem::exists(keybinderUser); - MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, mGrab); + if(!keybinderUserExists) + { + std::string input2 = (mCfgMgr.getUserConfigPath() / "input_v2.xml").string(); + if(boost::filesystem::exists(input2)) { + boost::filesystem::copy_file(input2, keybinderUser); + keybinderUserExists = boost::filesystem::exists(keybinderUser); + } + } + + // find correct path to the game controller bindings + const std::string localdefault = mCfgMgr.getLocalPath().string() + "/gamecontrollerdb.cfg"; + const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/gamecontrollerdb.cfg"; + std::string gameControllerdb; + if (boost::filesystem::exists(localdefault)) + gameControllerdb = localdefault; + else if (boost::filesystem::exists(globaldefault)) + gameControllerdb = globaldefault; + else + gameControllerdb = ""; //if it doesn't exist, pass in an empty string + + MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists, gameControllerdb, mGrab); mEnvironment.setInputManager (input); MWGui::WindowManager* window = new MWGui::WindowManager( diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 82fda060ed..070136dfd7 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -290,7 +290,7 @@ public: std::streamsize write(const char *str, std::streamsize size) { // Make a copy for null termination - std::string tmp (str, size); + std::string tmp (str, static_cast(size)); // Write string to Visual Studio Debug output OutputDebugString (tmp.c_str ()); return size; diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index a53d8d9dcd..79477d883f 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -37,11 +37,23 @@ namespace MWBase virtual bool getControlSwitch (const std::string& sw) = 0; virtual std::string getActionDescription (int action) = 0; - virtual std::string getActionBindingName (int action) = 0; - virtual std::vector getActionSorting () = 0; + virtual std::string getActionKeyBindingName (int action) = 0; + virtual std::string getActionControllerBindingName (int action) = 0; + virtual std::string sdlControllerAxisToString(int axis) = 0; + virtual std::string sdlControllerButtonToString(int button) = 0; + ///Actions available for binding to keyboard buttons + virtual std::vector getActionKeySorting() = 0; + ///Actions available for binding to controller buttons + virtual std::vector getActionControllerSorting() = 0; virtual int getNumActions() = 0; - virtual void enableDetectingBindingMode (int action) = 0; - virtual void resetToDefaultBindings() = 0; + ///If keyboard is true, only pay attention to keyboard events. If false, only pay attention to controller events (excluding esc) + virtual void enableDetectingBindingMode (int action, bool keyboard) = 0; + virtual void resetToDefaultKeyBindings() = 0; + virtual void resetToDefaultControllerBindings() = 0; + + /// Returns if the last used input device was a joystick or a keyboard + /// @return true if joystick, false otherwise + virtual bool joystickLastUsed() = 0; }; } diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index f3381a8fda..e71558de0b 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -20,7 +20,7 @@ namespace MWWorld namespace MWSound { class Sound; - class Sound_Decoder; + struct Sound_Decoder; typedef boost::shared_ptr DecoderPtr; } diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 2c4cb360d5..fdd51ef446 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -149,17 +149,14 @@ namespace MWBase /// \todo investigate, if we really need to expose every single lousy UI element to the outside world virtual MWGui::DialogueWindow* getDialogueWindow() = 0; - virtual MWGui::ContainerWindow* getContainerWindow() = 0; virtual MWGui::InventoryWindow* getInventoryWindow() = 0; - virtual MWGui::BookWindow* getBookWindow() = 0; - virtual MWGui::ScrollWindow* getScrollWindow() = 0; virtual MWGui::CountDialog* getCountDialog() = 0; virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0; virtual MWGui::TradeWindow* getTradeWindow() = 0; - virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow() = 0; - virtual MWGui::TravelWindow* getTravelWindow() = 0; - virtual MWGui::SpellWindow* getSpellWindow() = 0; - virtual MWGui::Console* getConsole() = 0; + + virtual void updateSpellWindow() = 0; + + virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0; virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0; @@ -181,12 +178,6 @@ namespace MWBase virtual void configureSkills (const SkillList& major, const SkillList& minor) = 0; ///< configure skill groups, each set contains the skill ID for that group. - virtual void setReputation (int reputation) = 0; - ///< set the current reputation value - - virtual void setBounty (int bounty) = 0; - ///< set the current bounty value - virtual void updateSkillArea() = 0; ///< update display of skills, factions, birth sign, reputation and bounty @@ -303,6 +294,12 @@ namespace MWBase virtual void startTraining(MWWorld::Ptr actor) = 0; virtual void startRepair(MWWorld::Ptr actor) = 0; virtual void startRepairItem(MWWorld::Ptr item) = 0; + virtual void startTravel(const MWWorld::Ptr& actor) = 0; + virtual void startSpellBuying(const MWWorld::Ptr& actor) = 0; + virtual void startTrade(const MWWorld::Ptr& actor) = 0; + virtual void openContainer(const MWWorld::Ptr& container, bool loot) = 0; + virtual void showBook(const MWWorld::Ptr& item, bool showTakeButton) = 0; + virtual void showScroll(const MWWorld::Ptr& item, bool showTakeButton) = 0; virtual void showSoulgemDialog (MWWorld::Ptr item) = 0; @@ -332,9 +329,8 @@ namespace MWBase /// Does the current stack of GUI-windows permit saving? virtual bool isSavingAllowed() const = 0; - /// Returns the current Modal - /** Used to send exit command to active Modal when Esc is pressed **/ - virtual MWGui::WindowModal* getCurrentModal() const = 0; + /// Send exit command to active Modal window + virtual void exitCurrentModal() = 0; /// Sets the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 9eb272e1b8..9e6c6d9bf3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -49,7 +49,7 @@ namespace MWRender namespace MWMechanics { - class Movement; + struct Movement; } namespace MWWorld @@ -205,10 +205,8 @@ namespace MWBase ///< Return a pointer to a liveCellRef which contains \a ptr. /// \note Search is limited to the active cells. - /// \todo enable reference in the OGRE scene virtual void enable (const MWWorld::Ptr& ptr) = 0; - /// \todo disable reference in the OGRE scene virtual void disable (const MWWorld::Ptr& ptr) = 0; virtual void advanceTime (double hours) = 0; diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 316ba3ab6e..2abd071bd0 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -155,7 +155,7 @@ namespace MWClass bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Apparatus; + return (npcServices & ESM::NPC::Apparatus) != 0; } float Apparatus::getWeight(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 64043157dc..686f5af619 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -154,9 +154,9 @@ namespace MWClass const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - float iWeight = gmst.find (typeGmst)->getInt(); + float iWeight = floor(gmst.find(typeGmst)->getFloat()); - float epsilon = 5e-4; + float epsilon = 0.0005f; if (ref->mBase->mData.mWeight == 0) return ESM::Skill::Unarmored; @@ -245,7 +245,8 @@ namespace MWClass else typeText = "#{sHeavy}"; - text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor); + text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(getEffectiveArmorRating(ptr, + MWBase::Environment::get().getWorld()->getPlayerPtr())); int remainingHealth = getItemHealth(ptr); text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" @@ -261,7 +262,7 @@ namespace MWClass info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); + info.remainingEnchantCharge = static_cast(ptr.getCellRef().getEnchantmentCharge()); info.text = text; @@ -290,6 +291,22 @@ namespace MWClass return record->mId; } + int Armor::getEffectiveArmorRating(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + + int armorSkillType = getEquipmentSkill(ptr); + int armorSkill = actor.getClass().getSkill(actor, armorSkillType); + + const MWBase::World *world = MWBase::Environment::get().getWorld(); + int iBaseArmorSkill = world->getStore().get().find("iBaseArmorSkill")->getInt(); + + if(ref->mBase->mData.mWeight == 0) + return ref->mBase->mData.mArmor; + else + return ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill; + } + std::pair Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 8c8e74cf41..21d711a0d3 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -86,6 +86,9 @@ namespace MWClass virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const; virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; + + /// Get the effective armor rating, factoring in the actor's skills, for the given armor. + virtual int getEffectiveArmorRating(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 0fa686dda4..b387a3e9f1 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -203,7 +203,7 @@ namespace MWClass info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); + info.remainingEnchantCharge = static_cast(ptr.getCellRef().getEnchantmentCharge()); info.text = text; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e44f4ffc12..8404b95234 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -1,6 +1,8 @@ #include "creature.hpp" +#include + #include #include @@ -103,9 +105,9 @@ namespace MWClass data->mCreatureStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mData.mEndurance); data->mCreatureStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mData.mPersonality); data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck); - data->mCreatureStats.setHealth (ref->mBase->mData.mHealth); - data->mCreatureStats.setMagicka (ref->mBase->mData.mMana); - data->mCreatureStats.setFatigue (ref->mBase->mData.mFatigue); + data->mCreatureStats.setHealth(static_cast(ref->mBase->mData.mHealth)); + data->mCreatureStats.setMagicka(static_cast(ref->mBase->mData.mMana)); + data->mCreatureStats.setFatigue(static_cast(ref->mBase->mData.mFatigue)); data->mCreatureStats.setLevel(ref->mBase->mData.mLevel); @@ -164,7 +166,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); MWRender::Actors& actors = renderingInterface.getActors(); - actors.insertCreature(ptr, model, ref->mBase->mFlags & ESM::Creature::Weapon); + actors.insertCreature(ptr, model, (ref->mBase->mFlags & ESM::Creature::Weapon) != 0); } void Creature::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const @@ -249,7 +251,7 @@ namespace MWClass float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat); - if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f) + if(OEngine::Misc::Rng::rollProbability() >= hitchance/100.0f) { victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); @@ -288,9 +290,7 @@ namespace MWClass if(attack) { damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); - damage *= gmst.find("fDamageStrengthBase")->getFloat() + - (stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.find("fDamageStrengthMult")->getFloat() * 0.1); - MWMechanics::adjustWeaponDamage(damage, weapon); + MWMechanics::adjustWeaponDamage(damage, weapon, ptr); MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr); } @@ -355,7 +355,7 @@ namespace MWClass if(!object.isEmpty()) getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); - if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player") + if(setOnPcHitMe && !attacker.isEmpty() && attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) { const std::string &script = ptr.get()->mBase->mScript; /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ @@ -376,9 +376,8 @@ namespace MWClass // Check for knockdown float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat(); float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() - * getGmst().iKnockDownOddsMult->getInt() * 0.01 + getGmst().iKnockDownOddsBase->getInt(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (ishealth && agilityTerm <= damage && knockdownTerm <= roll) + * getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt(); + if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99()) { getCreatureStats(ptr).setKnockedDown(true); @@ -493,7 +492,7 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return (ref->mBase->mFlags & ESM::Creature::Weapon); + return (ref->mBase->mFlags & ESM::Creature::Weapon) != 0; } std::string Creature::getScript (const MWWorld::Ptr& ptr) const @@ -508,7 +507,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mFlags & ESM::Creature::Essential; + return (ref->mBase->mFlags & ESM::Creature::Essential) != 0; } void Creature::registerSelf() @@ -528,7 +527,7 @@ namespace MWClass MWMechanics::CreatureStats& stats = getCreatureStats(ptr); const GMST& gmst = getGmst(); - float walkSpeed = gmst.fMinWalkSpeedCreature->getFloat() + 0.01 * stats.getAttribute(ESM::Attribute::Speed).getModified() + float walkSpeed = gmst.fMinWalkSpeedCreature->getFloat() + 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified() * (gmst.fMaxWalkSpeedCreature->getFloat() - gmst.fMinWalkSpeedCreature->getFloat()); const MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -626,7 +625,7 @@ namespace MWClass float Creature::getCapacity (const MWWorld::Ptr& ptr) const { const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); - return stats.getAttribute(0).getModified()*5; + return static_cast(stats.getAttribute(0).getModified() * 5); } float Creature::getEncumbrance (const MWWorld::Ptr& ptr) const @@ -682,7 +681,7 @@ namespace MWClass ++sound; } if(!sounds.empty()) - return sounds[(int)(rand()/(RAND_MAX+1.0)*sounds.size())]->mSound; + return sounds[OEngine::Misc::Rng::rollDice(sounds.size())]->mSound; } if (type == ESM::SoundGenerator::Land) @@ -713,7 +712,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mFlags & ESM::Creature::Flies; + return (ref->mBase->mFlags & ESM::Creature::Flies) != 0; } bool Creature::canSwim(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 10b9b437da..2d39881b1f 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -167,19 +167,19 @@ namespace MWClass if (opening) { MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, - closeSound, 0.5); - float offset = ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0; + closeSound, 0.5f); + float offset = ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265f * 2.0f; action->setSoundOffset(offset); action->setSound(openSound); } else { MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, - openSound, 0.5); - float offset = 1.0 - ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0; + openSound, 0.5f); + float offset = 1.0f - ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265f * 2.0f; //most if not all door have closing bang somewhere in the middle of the sound, //so we divide offset by two - action->setSoundOffset(offset * 0.5); + action->setSoundOffset(offset * 0.5f); action->setSound(closeSound); } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 9f662a60ea..de43e818e9 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -192,7 +192,7 @@ namespace MWClass bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Ingredients; + return (npcServices & ESM::NPC::Ingredients) != 0; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 35a21b63e4..90c708f970 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -50,7 +50,7 @@ namespace MWClass assert (ref->mBase != NULL); if(!model.empty()) - physics.addObject(ptr, model, ref->mBase->mData.mFlags & ESM::Light::Carry); + physics.addObject(ptr, model, (ref->mBase->mData.mFlags & ESM::Light::Carry) != 0); if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)) MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, @@ -205,7 +205,7 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); if (ptr.getCellRef().getCharge() == -1) - return ref->mBase->mData.mTime; + return static_cast(ref->mBase->mData.mTime); else return ptr.getCellRef().getChargeFloat(); } @@ -221,7 +221,7 @@ namespace MWClass bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Lights; + return (npcServices & ESM::NPC::Lights) != 0; } float Light::getWeight(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index e78c43eee3..478c50301d 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -173,7 +173,7 @@ namespace MWClass bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Picks; + return (npcServices & ESM::NPC::Picks) != 0; } int Lockpick::getItemMaxHealth (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index f9cfd8e0b6..f5daafeec2 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -259,7 +259,7 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mData.mIsKey; + return ref->mBase->mData.mIsKey != 0; } } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index cedff12918..1d58dc87e3 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -5,6 +5,8 @@ #include +#include + #include #include #include @@ -66,12 +68,12 @@ namespace double i = floor(d); d -= i; if(d < 0.5) - return i; + return static_cast(i); if(d > 0.5) - return i + 1.0; + return static_cast(i) + 1; if(is_even(i)) - return i; - return i + 1.0; + return static_cast(i); + return static_cast(i) + 1; } void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats) @@ -116,7 +118,7 @@ namespace continue; // is this a minor or major skill? - float add=0.2; + float add=0.2f; for (int k=0; k<5; ++k) { if (class_->mData.mSkills[k][0] == j) @@ -149,7 +151,7 @@ namespace || class_->mData.mAttribute[1] == ESM::Attribute::Endurance) multiplier += 1; - creatureStats.setHealth(static_cast (0.5 * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1)); + creatureStats.setHealth(floor(0.5f * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1)); } /** @@ -279,8 +281,6 @@ namespace MWClass gmst.fKnockDownMult = store.find("fKnockDownMult"); gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult"); gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase"); - gmst.fDamageStrengthBase = store.find("fDamageStrengthBase"); - gmst.fDamageStrengthMult = store.find("fDamageStrengthMult"); gmst.fCombatArmorMinMult = store.find("fCombatArmorMinMult"); inited = true; @@ -475,7 +475,6 @@ namespace MWClass void Npc::hit(const MWWorld::Ptr& ptr, int type) const { MWBase::World *world = MWBase::Environment::get().getWorld(); - const GMST& gmst = getGmst(); const MWWorld::Store &store = world->getStore().get(); @@ -507,7 +506,7 @@ namespace MWClass if(otherstats.isDead()) // Can't hit dead actors return; - if(ptr.getRefData().getHandle() == "player") + if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->setEnemy(victim); int weapskill = ESM::Skill::HandToHand; @@ -516,7 +515,7 @@ namespace MWClass float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill)); - if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f) + if (OEngine::Misc::Rng::rollProbability() >= hitchance / 100.0f) { othercls.onHit(victim, 0.0f, false, weapon, ptr, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); @@ -538,10 +537,8 @@ namespace MWClass if(attack) { damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); - damage *= gmst.fDamageStrengthBase->getFloat() + - (stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.fDamageStrengthMult->getFloat() * 0.1); } - MWMechanics::adjustWeaponDamage(damage, weapon); + MWMechanics::adjustWeaponDamage(damage, weapon, ptr); MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr); healthdmg = true; } @@ -549,7 +546,7 @@ namespace MWClass { MWMechanics::getHandToHandDamage(ptr, victim, damage, healthdmg); } - if(ptr.getRefData().getHandle() == "player") + if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { skillUsageSucceeded(ptr, weapskill, 0); @@ -625,7 +622,7 @@ namespace MWClass if(!object.isEmpty()) getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); - if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player") + if(setOnPcHitMe && !attacker.isEmpty() && attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) { const std::string &script = ptr.getClass().getScript(ptr); /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ @@ -648,8 +645,7 @@ namespace MWClass const GMST& gmst = getGmst(); int chance = store.get().find("iVoiceHitOdds")->getInt(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (roll < chance) + if (OEngine::Misc::Rng::roll0to99() < chance) { MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); } @@ -657,9 +653,8 @@ namespace MWClass // Check for knockdown float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat(); float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() - * gmst.iKnockDownOddsMult->getInt() * 0.01 + gmst.iKnockDownOddsBase->getInt(); - roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (ishealth && agilityTerm <= damage && knockdownTerm <= roll) + * gmst.iKnockDownOddsMult->getInt() * 0.01f + gmst.iKnockDownOddsBase->getInt(); + if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99()) { getCreatureStats(ptr).setKnockedDown(true); @@ -685,12 +680,12 @@ namespace MWClass MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_LeftGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet }; - int hitslot = hitslots[(int)(::rand()/(RAND_MAX+1.0)*20.0)]; + int hitslot = hitslots[OEngine::Misc::Rng::rollDice(20)]; float unmitigatedDamage = damage; float x = damage / (damage + getArmorRating(ptr)); damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x); - int damageDiff = unmitigatedDamage - damage; + int damageDiff = static_cast(unmitigatedDamage - damage); if (damage < 1) damage = 1; @@ -708,7 +703,7 @@ namespace MWClass if (armorhealth == 0) armor = *inv.unequipItem(armor, ptr); - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0); switch(armor.getClass().getEquipmentSkill(armor)) @@ -724,7 +719,7 @@ namespace MWClass break; } } - else if(ptr.getRefData().getHandle() == "player") + else if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) skillUsageSucceeded(ptr, ESM::Skill::Unarmored, 0); } } @@ -737,7 +732,7 @@ namespace MWClass if(damage > 0.0f) { sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->activateHitOverlay(); } float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; @@ -815,7 +810,7 @@ namespace MWClass const MWWorld::Ptr& actor) const { // player got activated by another NPC - if(ptr.getRefData().getHandle() == "player") + if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) return boost::shared_ptr(new MWWorld::ActionTalk(actor)); // Werewolfs can't activate NPCs @@ -938,7 +933,7 @@ namespace MWClass gmst.fJumpEncumbranceMultiplier->getFloat() * (1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr)); - float a = npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified(); + float a = static_cast(npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified()); float b = 0.0f; if(a > 50.0f) { @@ -993,7 +988,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mFlags & ESM::NPC::Essential; + return (ref->mBase->mFlags & ESM::NPC::Essential) != 0; } void Npc::registerSelf() @@ -1086,7 +1081,6 @@ namespace MWClass MWMechanics::NpcStats &stats = getNpcStats(ptr); MWWorld::InventoryStore &invStore = getInventoryStore(ptr); - int iBaseArmorSkill = store.find("iBaseArmorSkill")->getInt(); float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat(); float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat(); int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified(); @@ -1098,19 +1092,11 @@ namespace MWClass if (it == invStore.end() || it->getTypeName() != typeid(ESM::Armor).name()) { // unarmored - ratings[i] = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill); + ratings[i] = static_cast((fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill)); } else { - MWWorld::LiveCellRef *ref = it->get(); - - int armorSkillType = it->getClass().getEquipmentSkill(*it); - int armorSkill = stats.getSkill(armorSkillType).getModified(); - - if(ref->mBase->mData.mWeight == 0) - ratings[i] = ref->mBase->mData.mArmor; - else - ratings[i] = ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill; + ratings[i] = it->getClass().getEffectiveArmorRating(*it, ptr); } } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 9aece7368c..27beeb626e 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -5,7 +5,7 @@ namespace ESM { - class GameSetting; + struct GameSetting; } namespace MWClass @@ -38,8 +38,6 @@ namespace MWClass const ESM::GameSetting *fKnockDownMult; const ESM::GameSetting *iKnockDownOddsMult; const ESM::GameSetting *iKnockDownOddsBase; - const ESM::GameSetting *fDamageStrengthBase; - const ESM::GameSetting *fDamageStrengthMult; const ESM::GameSetting *fCombatArmorMinMult; }; diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index bd06f89fc8..ee299ab4f8 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -185,7 +185,7 @@ namespace MWClass bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Potions; + return (npcServices & ESM::NPC::Potions) != 0; } float Potion::getWeight(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index a11725f267..da22e9be6c 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -172,7 +172,7 @@ namespace MWClass bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::Probes; + return (npcServices & ESM::NPC::Probes) != 0; } int Probe::getItemMaxHealth (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index e9c4ac9b19..c02146f122 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -172,7 +172,7 @@ namespace MWClass bool Repair::canSell (const MWWorld::Ptr& item, int npcServices) const { - return npcServices & ESM::NPC::RepairItem; + return (npcServices & ESM::NPC::RepairItem) != 0; } float Repair::getWeight(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index d1a44fd0e3..a484ad6683 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -345,7 +345,7 @@ namespace MWClass info.enchant = ref->mBase->mEnchant; if (!info.enchant.empty()) - info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); + info.remainingEnchantCharge = static_cast(ptr.getCellRef().getEnchantmentCharge()); if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 1d1f655aaa..b928738ddd 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -179,10 +179,7 @@ namespace MWDialogue bool isCompanion = !mActor.getClass().getScript(mActor).empty() && mActor.getRefData().getLocals().getIntVar(mActor.getClass().getScript(mActor), "companion"); if (isCompanion) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion); MWBase::Environment::get().getWindowManager()->showCompanionWindow(mActor); - } } bool DialogueManager::compile (const std::string& cmd,std::vector& code) @@ -383,7 +380,8 @@ namespace MWDialogue || services & ESM::NPC::Misc) windowServices |= MWGui::DialogueWindow::Service_Trade; - if(mActor.getTypeName() == typeid(ESM::NPC).name() && !mActor.get()->mBase->mTransport.empty()) + if((mActor.getTypeName() == typeid(ESM::NPC).name() && !mActor.get()->mBase->getTransport().empty()) + || (mActor.getTypeName() == typeid(ESM::Creature).name() && !mActor.get()->mBase->getTransport().empty())) windowServices |= MWGui::DialogueWindow::Service_Travel; if (services & ESM::NPC::Spells) @@ -444,7 +442,7 @@ namespace MWDialogue if (mActor.getClass().isNpc()) { MWMechanics::NpcStats& npcStats = mActor.getClass().getNpcStats(mActor); - npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange); + npcStats.setBaseDisposition(static_cast(npcStats.getBaseDisposition() + mPermanentDispositionChange)); } mPermanentDispositionChange = 0; mTemporaryDispositionChange = 0; @@ -521,7 +519,7 @@ namespace MWDialogue mPermanentDispositionChange += perm; // change temp disposition so that final disposition is between 0...100 - int curDisp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor); + float curDisp = static_cast(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor)); if (curDisp + mTemporaryDispositionChange < 0) mTemporaryDispositionChange = -curDisp; else if (curDisp + mTemporaryDispositionChange > 100) @@ -564,7 +562,7 @@ namespace MWDialogue int DialogueManager::getTemporaryDispositionChange() const { - return mTemporaryDispositionChange; + return static_cast(mTemporaryDispositionChange); } void DialogueManager::applyDispositionChange(int delta) diff --git a/apps/openmw/mwgui/backgroundimage.cpp b/apps/openmw/mwgui/backgroundimage.cpp index 9c07c5780b..ee966c189c 100644 --- a/apps/openmw/mwgui/backgroundimage.cpp +++ b/apps/openmw/mwgui/backgroundimage.cpp @@ -41,8 +41,8 @@ void BackgroundImage::adjustSize() MyGUI::IntSize screenSize = getSize(); - int leftPadding = std::max(0.0, (screenSize.width - screenSize.height * mAspect) / 2); - int topPadding = std::max(0.0, (screenSize.height - screenSize.width / mAspect) / 2); + int leftPadding = std::max(0, static_cast(screenSize.width - screenSize.height * mAspect) / 2); + int topPadding = std::max(0, static_cast(screenSize.height - screenSize.width / mAspect) / 2); mChild->setCoord(leftPadding, topPadding, screenSize.width - leftPadding*2, screenSize.height - topPadding*2); } diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index c9cfc8c2c1..962e594aeb 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -16,8 +16,8 @@ namespace MWGui { struct TypesetBookImpl; -struct PageDisplay; -struct BookPageImpl; +class PageDisplay; +class BookPageImpl; static bool ucsSpace (int codePoint); static bool ucsLineBreak (int codePoint); @@ -326,7 +326,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter mLine = NULL; } - void sectionBreak (float margin) + void sectionBreak (int margin) { add_partial_text(); @@ -465,7 +465,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter { MyGUI::GlyphInfo* gi = style->mFont->getGlyphInfo (stream.peek ()); if (gi) - space_width += gi->advance + gi->bearingX; + space_width += static_cast(gi->advance + gi->bearingX); stream.consume (); } @@ -475,7 +475,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter { MyGUI::GlyphInfo* gi = style->mFont->getGlyphInfo (stream.peek ()); if (gi) - word_width += gi->advance + gi->bearingX; + word_width += static_cast(gi->advance + gi->bearingX); stream.consume (); } @@ -623,15 +623,15 @@ namespace RenderXform (MyGUI::ICroppedRectangle* croppedParent, MyGUI::RenderTargetInfo const & renderTargetInfo) { - clipTop = croppedParent->_getMarginTop (); - clipLeft = croppedParent->_getMarginLeft (); - clipRight = croppedParent->getWidth () - croppedParent->_getMarginRight (); - clipBottom = croppedParent->getHeight () - croppedParent->_getMarginBottom (); + clipTop = static_cast(croppedParent->_getMarginTop()); + clipLeft = static_cast(croppedParent->_getMarginLeft ()); + clipRight = static_cast(croppedParent->getWidth () - croppedParent->_getMarginRight ()); + clipBottom = static_cast(croppedParent->getHeight() - croppedParent->_getMarginBottom()); - absoluteLeft = croppedParent->getAbsoluteLeft(); - absoluteTop = croppedParent->getAbsoluteTop(); - leftOffset = renderTargetInfo.leftOffset; - topOffset = renderTargetInfo.topOffset; + absoluteLeft = static_cast(croppedParent->getAbsoluteLeft()); + absoluteTop = static_cast(croppedParent->getAbsoluteTop()); + leftOffset = static_cast(renderTargetInfo.leftOffset); + topOffset = static_cast(renderTargetInfo.topOffset); pixScaleX = renderTargetInfo.pixScaleX; pixScaleY = renderTargetInfo.pixScaleY; @@ -1136,7 +1136,7 @@ public: MyGUI::Colour colour = isActive ? (this_->mItemActive ? run.mStyle->mActiveColour: run.mStyle->mHotColour) : run.mStyle->mNormalColour; - glyphStream.reset (section.mRect.left + line.mRect.left + run.mLeft, line.mRect.top, colour); + glyphStream.reset(static_cast(section.mRect.left + line.mRect.left + run.mLeft), static_cast(line.mRect.top), colour); Utf8Stream stream (run.mRange); @@ -1164,7 +1164,7 @@ public: RenderXform renderXform (mCroppedParent, textFormat.mRenderItem->getRenderTarget()->getInfo()); - GlyphStream glyphStream (textFormat.mFont, mCoord.left, mCoord.top-mViewTop, + GlyphStream glyphStream(textFormat.mFont, static_cast(mCoord.left), static_cast(mCoord.top - mViewTop), -1 /*mNode->getNodeDepth()*/, vertices, renderXform); int visit_top = (std::max) (mViewTop, mViewTop + int (renderXform.clipTop )); diff --git a/apps/openmw/mwgui/bookpage.hpp b/apps/openmw/mwgui/bookpage.hpp index 458cf2a199..c7340ec7cf 100644 --- a/apps/openmw/mwgui/bookpage.hpp +++ b/apps/openmw/mwgui/bookpage.hpp @@ -71,7 +71,7 @@ namespace MWGui /// to begin when additional text is inserted. Pagination attempts to keep /// sections together on a single page. The margin parameter adds additional space /// before the next line of text. - virtual void sectionBreak (float margin = 0) = 0; + virtual void sectionBreak (int margin = 0) = 0; /// Changes the alignment for the current section of text. virtual void setSectionAlignment (Alignment sectionAlignment) = 0; diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index da0d1950e9..55a9b61918 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -73,7 +73,7 @@ namespace MWGui mPages.clear(); } - void BookWindow::open (MWWorld::Ptr book) + void BookWindow::open (MWWorld::Ptr book, bool showTakeButton) { mBook = book; @@ -90,7 +90,7 @@ namespace MWGui updatePages(); - setTakeButtonShow(true); + setTakeButtonShow(showTakeButton); } void BookWindow::exit() diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index ea3057a6f5..8ad4f68300 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -16,10 +16,7 @@ namespace MWGui virtual void exit(); - void open(MWWorld::Ptr book); - void setTakeButtonShow(bool show); - void nextPage(); - void prevPage(); + void open(MWWorld::Ptr book, bool showTakeButton); void setInventoryAllowed(bool allowed); protected: @@ -28,6 +25,10 @@ namespace MWGui void onCloseButtonClicked (MyGUI::Widget* sender); void onTakeButtonClicked (MyGUI::Widget* sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void setTakeButtonShow(bool show); + + void nextPage(); + void prevPage(); void updatePages(); void clearPages(); diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index ab412f63b2..fb00d6a985 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -330,20 +330,7 @@ namespace MWGui updatePlayerHealth(); - //TODO This bit gets repeated a few times; wrap it in a function - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage == CSE_ReviewNext) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else if (mCreationStage >= CSE_ClassChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); - } - else - { - mCreationStage = CSE_ClassChosen; - } + handleDialogDone(CSE_ClassChosen, GM_Birth); } void CharacterCreation::onPickClassDialogBack() @@ -397,19 +384,7 @@ namespace MWGui mNameDialog = 0; } - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage == CSE_ReviewNext) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else if (mCreationStage >= CSE_NameChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Race); - } - else - { - mCreationStage = CSE_NameChosen; - } + handleDialogDone(CSE_NameChosen, GM_Race); } void CharacterCreation::onRaceDialogBack() @@ -456,19 +431,7 @@ namespace MWGui updatePlayerHealth(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage == CSE_ReviewNext) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else if (mCreationStage >= CSE_RaceChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class); - } - else - { - mCreationStage = CSE_RaceChosen; - } + handleDialogDone(CSE_RaceChosen, GM_Class); } void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow) @@ -484,15 +447,7 @@ namespace MWGui updatePlayerHealth(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage >= CSE_BirthSignChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else - { - mCreationStage = CSE_BirthSignChosen; - } + handleDialogDone(CSE_BirthSignChosen, GM_Review); } void CharacterCreation::onBirthSignDialogBack() @@ -543,19 +498,7 @@ namespace MWGui updatePlayerHealth(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage == CSE_ReviewNext) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else if (mCreationStage >= CSE_ClassChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); - } - else - { - mCreationStage = CSE_ClassChosen; - } + handleDialogDone(CSE_ClassChosen, GM_Birth); } void CharacterCreation::onCreateClassDialogBack() @@ -711,19 +654,7 @@ namespace MWGui updatePlayerHealth(); - MWBase::Environment::get().getWindowManager()->popGuiMode(); - if (mCreationStage == CSE_ReviewNext) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); - } - else if (mCreationStage >= CSE_ClassChosen) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Birth); - } - else - { - mCreationStage = CSE_ClassChosen; - } + handleDialogDone(CSE_ClassChosen, GM_Birth); } CharacterCreation::~CharacterCreation() @@ -739,4 +670,20 @@ namespace MWGui delete mReviewDialog; } + void CharacterCreation::handleDialogDone(CSE currentStage, int nextMode) + { + MWBase::Environment::get().getWindowManager()->popGuiMode(); + if (mCreationStage == CSE_ReviewNext) + { + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Review); + } + else if (mCreationStage >= currentStage) + { + MWBase::Environment::get().getWindowManager()->pushGuiMode((GuiMode)nextMode); + } + else + { + mCreationStage = currentStage; + } + } } diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index c2486c7f0b..a4515569db 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -104,6 +104,8 @@ namespace MWGui }; CSE mCreationStage; // Which state the character creating is in, controls back/next/ok buttons + + void handleDialogDone(CSE currentStage, int nextMode); }; } diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 8f709ec8da..fe47437cad 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -129,7 +129,7 @@ void CompanionWindow::updateEncumbranceBar() return; float capacity = mPtr.getClass().getCapacity(mPtr); float encumbrance = mPtr.getClass().getEncumbrance(mPtr); - mEncumbranceBar->setValue(encumbrance, capacity); + mEncumbranceBar->setValue(static_cast(encumbrance), static_cast(capacity)); if (mModel && mModel->hasProfit(mPtr)) { diff --git a/apps/openmw/mwgui/controllers.cpp b/apps/openmw/mwgui/controllers.cpp index ad804997ad..72f2eb7f3a 100644 --- a/apps/openmw/mwgui/controllers.cpp +++ b/apps/openmw/mwgui/controllers.cpp @@ -9,8 +9,8 @@ namespace MWGui { ControllerRepeatEvent::ControllerRepeatEvent() : - mInit(0.5), - mStep(0.1), + mInit(0.5f), + mStep(0.1f), mEnabled(true), mTimeLeft(0) { diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index eee86c6d21..1b07522f38 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -7,12 +7,14 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/dialoguemanager.hpp" #include "../mwmechanics/npcstats.hpp" @@ -20,12 +22,7 @@ #include "../mwworld/containerstore.hpp" #include "../mwworld/esmstore.hpp" -#include "../mwdialogue/dialoguemanagerimp.hpp" - #include "widgets.hpp" -#include "tradewindow.hpp" -#include "spellbuyingwindow.hpp" -#include "travelwindow.hpp" #include "bookpage.hpp" #include "journalbooks.hpp" // to_utf8_span @@ -337,51 +334,25 @@ namespace MWGui MWBase::Environment::get().getWorld()->getStore().get(); if (topic == gmst.find("sPersuasion")->getString()) - { mPersuasionDialog.setVisible(true); - } else if (topic == gmst.find("sCompanionShare")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion); MWBase::Environment::get().getWindowManager()->showCompanionWindow(mPtr); - } else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused()) { if (topic == gmst.find("sBarter")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter); - MWBase::Environment::get().getWindowManager()->getTradeWindow()->startTrade(mPtr); - } + MWBase::Environment::get().getWindowManager()->startTrade(mPtr); else if (topic == gmst.find("sSpells")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying); - MWBase::Environment::get().getWindowManager()->getSpellBuyingWindow()->startSpellBuying(mPtr); - } + MWBase::Environment::get().getWindowManager()->startSpellBuying(mPtr); else if (topic == gmst.find("sTravel")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel); - MWBase::Environment::get().getWindowManager()->getTravelWindow()->startTravel(mPtr); - } + MWBase::Environment::get().getWindowManager()->startTravel(mPtr); else if (topic == gmst.find("sSpellMakingMenuTitle")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation); MWBase::Environment::get().getWindowManager()->startSpellMaking (mPtr); - } else if (topic == gmst.find("sEnchanting")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting); MWBase::Environment::get().getWindowManager()->startEnchanting (mPtr); - } else if (topic == gmst.find("sServiceTrainingTitle")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training); MWBase::Environment::get().getWindowManager()->startTraining (mPtr); - } else if (topic == gmst.find("sRepair")->getString()) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair); MWBase::Environment::get().getWindowManager()->startRepair (mPtr); - } } } } @@ -440,8 +411,6 @@ namespace MWGui bool isCompanion = !mPtr.getClass().getScript(mPtr).empty() && mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion"); - bool anyService = mServices > 0 || isCompanion || mPtr.getTypeName() == typeid(ESM::NPC).name(); - const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -472,7 +441,7 @@ namespace MWGui if (isCompanion) mTopicsList->addItem(gmst.find("sCompanionShare")->getString()); - if (anyService) + if (mTopicsList->getItemCount() > 0) mTopicsList->addSeparator(); @@ -549,7 +518,7 @@ namespace MWGui size_t range = book->getSize().second - viewHeight; mScrollBar->setScrollRange(range); mScrollBar->setScrollPosition(range-1); - mScrollBar->setTrackSize(viewHeight / static_cast(book->getSize().second) * mScrollBar->getLineSize()); + mScrollBar->setTrackSize(static_cast(viewHeight / static_cast(book->getSize().second) * mScrollBar->getLineSize())); onScrollbarMoved(mScrollBar, range-1); } else @@ -637,14 +606,14 @@ namespace MWGui if (dispositionVisible && !dispositionWasVisible) { mDispositionBar->setVisible(true); - float offset = mDispositionBar->getHeight()+5; + int offset = mDispositionBar->getHeight()+5; mTopicsList->setCoord(mTopicsList->getCoord() + MyGUI::IntCoord(0,offset,0,-offset)); mTopicsList->adjustSize(); } else if (!dispositionVisible && dispositionWasVisible) { mDispositionBar->setVisible(false); - float offset = mDispositionBar->getHeight()+5; + int offset = mDispositionBar->getHeight()+5; mTopicsList->setCoord(mTopicsList->getCoord() - MyGUI::IntCoord(0,offset,0,-offset)); mTopicsList->adjustSize(); } diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index a4e67e9b14..eb458be500 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -24,7 +24,6 @@ #include "../mwmechanics/npcstats.hpp" #include "inventorywindow.hpp" -#include "console.hpp" #include "spellicons.hpp" #include "itemmodel.hpp" #include "draganddrop.hpp" @@ -262,7 +261,7 @@ namespace MWGui void HUD::setDrowningTimeLeft(float time, float maxTime) { - size_t progress = time/maxTime*200.0; + size_t progress = static_cast(time / maxTime * 200); mDrowning->setProgressPosition(progress); bool isDrowning = (progress == 0); @@ -309,7 +308,7 @@ namespace MWGui MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject(); if (mode == GM_Console) - MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); + MWBase::Environment::get().getWindowManager()->setConsoleSelectedObject(object); else if ((mode == GM_Container) || (mode == GM_Inventory)) { // pick up object @@ -631,7 +630,7 @@ namespace MWGui mEnemyHealth->setProgressRange(100); // Health is usually cast to int before displaying. Actors die whenever they are < 1 health. // Therefore any value < 1 should show as an empty health bar. We do the same in statswindow :) - mEnemyHealth->setProgressPosition(int(stats.getHealth().getCurrent()) / stats.getHealth().getModified() * 100); + mEnemyHealth->setProgressPosition(static_cast(stats.getHealth().getCurrent() / stats.getHealth().getModified() * 100)); static const float fNPCHealthBarFade = MWBase::Environment::get().getWorld()->getStore().get().find("fNPCHealthBarFade")->getFloat(); if (fNPCHealthBarFade > 0.f) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4270c4be16..80b246e840 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -23,9 +23,6 @@ #include "../mwbase/scriptmanager.hpp" #include "../mwrender/characterpreview.hpp" -#include "bookwindow.hpp" -#include "scrollwindow.hpp" -#include "spellwindow.hpp" #include "itemview.hpp" #include "inventoryitemmodel.hpp" #include "sortfilteritemmodel.hpp" @@ -101,7 +98,7 @@ namespace MWGui void InventoryWindow::adjustPanes() { const float aspect = 0.5; // fixed aspect ratio for the avatar image - float leftPaneWidth = (mMainWidget->getSize().height-44-mArmorRating->getHeight()) * aspect; + int leftPaneWidth = static_cast((mMainWidget->getSize().height - 44 - mArmorRating->getHeight()) * aspect); mLeftPane->setSize( leftPaneWidth, mMainWidget->getSize().height-44 ); mRightPane->setCoord( mLeftPane->getPosition().left + leftPaneWidth + 4, mRightPane->getPosition().top, @@ -153,10 +150,10 @@ namespace MWGui } MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); - MyGUI::IntPoint pos (Settings::Manager::getFloat(setting + " x", "Windows") * viewSize.width, - Settings::Manager::getFloat(setting + " y", "Windows") * viewSize.height); - MyGUI::IntSize size (Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width, - Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height); + MyGUI::IntPoint pos(static_cast(Settings::Manager::getFloat(setting + " x", "Windows") * viewSize.width), + static_cast(Settings::Manager::getFloat(setting + " y", "Windows") * viewSize.height)); + MyGUI::IntSize size(static_cast(Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width), + static_cast(Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height)); if (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight()) mPreviewResize = true; @@ -317,8 +314,7 @@ namespace MWGui void InventoryWindow::updateItemView() { - if (MWBase::Environment::get().getWindowManager()->getSpellWindow()) - MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells(); + MWBase::Environment::get().getWindowManager()->updateSpellWindow(); mItemView->update(); mPreviewDirty = true; @@ -432,13 +428,6 @@ namespace MWGui action->execute (MWBase::Environment::get().getWorld()->getPlayerPtr()); - // this is necessary for books/scrolls: if they are already in the player's inventory, - // the "Take" button should not be visible. - // NOTE: the take button is "reset" when the window opens, so we can safely do the following - // without screwing up future book windows - MWBase::Environment::get().getWindowManager()->getBookWindow()->setTakeButtonShow(false); - MWBase::Environment::get().getWindowManager()->getScrollWindow()->setTakeButtonShow(false); - mSkippedToEquip = MWWorld::Ptr(); } else @@ -519,7 +508,7 @@ namespace MWGui float capacity = player.getClass().getCapacity(player); float encumbrance = player.getClass().getEncumbrance(player); mTradeModel->adjustEncumbrance(encumbrance); - mEncumbranceBar->setValue(encumbrance, capacity); + mEncumbranceBar->setValue(static_cast(encumbrance), static_cast(capacity)); } void InventoryWindow::onFrame() @@ -568,8 +557,7 @@ namespace MWGui void InventoryWindow::notifyContentChanged() { // update the spell window just in case new enchanted items were added to inventory - if (MWBase::Environment::get().getWindowManager()->getSpellWindow()) - MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells(); + MWBase::Environment::get().getWindowManager()->updateSpellWindow(); MWBase::Environment::get().getMechanicsManager()->updateMagicEffects( MWBase::Environment::get().getWorld()->getPlayerPtr()); @@ -626,8 +614,7 @@ namespace MWGui MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, MWWorld::Ptr(), count); - if (MWBase::Environment::get().getWindowManager()->getSpellWindow()) - MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells(); + MWBase::Environment::get().getWindowManager()->updateSpellWindow(); } void InventoryWindow::cycle(bool next) @@ -653,16 +640,13 @@ namespace MWGui if (selected != -1) lastId = model.getItem(selected).mBase.getCellRef().getRefId(); ItemModel::ModelIndex cycled = selected; - while (!found) + for (unsigned int i=0; igetViewOffset().left + _rel*0.3 > 0) + if (mScrollView->getViewOffset().left + _rel*0.3f > 0) mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mScrollView->setViewOffset(MyGUI::IntPoint(mScrollView->getViewOffset().left + _rel*0.3, 0)); + mScrollView->setViewOffset(MyGUI::IntPoint(static_cast(mScrollView->getViewOffset().left + _rel*0.3f), 0)); } void ItemView::setSize(const MyGUI::IntSize &_value) diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 58873c5660..5c0a6ec5f2 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -1,5 +1,7 @@ #include +#include + #include "../mwbase/windowmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/world.hpp" @@ -17,7 +19,7 @@ namespace MWGui { JailScreen::JailScreen() : WindowBase("openmw_jail_screen.layout"), - mTimeAdvancer(0.01), + mTimeAdvancer(0.01f), mDays(1), mFadeTimeRemaining(0) { @@ -66,7 +68,7 @@ namespace MWGui void JailScreen::onJailProgressChanged(int cur, int /*total*/) { mProgressBar->setScrollPosition(0); - mProgressBar->setTrackSize(cur / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); + mProgressBar->setTrackSize(static_cast(cur / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize())); } void JailScreen::onJailFinished() @@ -83,7 +85,7 @@ namespace MWGui std::set skills; for (int day=0; day (RAND_MAX) + 1) * ESM::Skill::Length; + int skill = OEngine::Misc::Rng::rollDice(ESM::Skill::Length); skills.insert(skill); MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill); diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 9e3343c782..3204c65482 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -15,6 +15,8 @@ #include #include +#include + #include #include "../mwbase/environment.hpp" @@ -33,8 +35,8 @@ namespace MWGui : mSceneMgr(sceneMgr) , mWindow(rw) , WindowBase("openmw_loading_screen.layout") - , mLastRenderTime(0.f) - , mLastWallpaperChangeTime(0.f) + , mLastRenderTime(0) + , mLastWallpaperChangeTime(0) , mProgress(0) , mVSyncWasEnabled(false) { @@ -146,7 +148,7 @@ namespace MWGui if (!mResources.empty()) { - std::string const & randomSplash = mResources.at (rand() % mResources.size()); + std::string const & randomSplash = mResources.at(OEngine::Misc::Rng::rollDice(mResources.size())); Ogre::TextureManager::getSingleton ().load (randomSplash, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); @@ -173,7 +175,7 @@ namespace MWGui return; mProgress = value; mProgressBar->setScrollPosition(0); - mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); + mProgressBar->setTrackSize(static_cast(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize())); draw(); } @@ -182,7 +184,7 @@ namespace MWGui mProgressBar->setScrollPosition(0); size_t value = mProgress + increase; mProgress = value; - mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); + mProgressBar->setTrackSize(static_cast(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize())); draw(); } @@ -193,7 +195,7 @@ namespace MWGui time = (time-2)*-1; mProgressBar->setTrackSize(50); - mProgressBar->setScrollPosition(time * (mProgressBar->getScrollRange()-1)); + mProgressBar->setScrollPosition(static_cast(time * (mProgressBar->getScrollRange() - 1))); draw(); } diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 13e2e39049..02e8ffdfed 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -244,14 +244,14 @@ namespace MWGui // Image space is -Y up, cells are Y up nY = 1 - (worldY - cellSize * cellY) / cellSize; - float cellDx = cellX - mCurX; - float cellDy = cellY - mCurY; + float cellDx = static_cast(cellX - mCurX); + float cellDy = static_cast(cellY - mCurY); markerPos.cellX = cellX; markerPos.cellY = cellY; - widgetPos = MyGUI::IntPoint(nX * mMapWidgetSize + (1+cellDx) * mMapWidgetSize, - nY * mMapWidgetSize - (cellDy-1) * mMapWidgetSize); + widgetPos = MyGUI::IntPoint(static_cast(nX * mMapWidgetSize + (1 + cellDx) * mMapWidgetSize), + static_cast(nY * mMapWidgetSize - (cellDy-1) * mMapWidgetSize)); } else { @@ -263,8 +263,8 @@ namespace MWGui markerPos.cellY = cellY; // Image space is -Y up, cells are Y up - widgetPos = MyGUI::IntPoint(nX * mMapWidgetSize + (1+(cellX-mCurX)) * mMapWidgetSize, - nY * mMapWidgetSize + (1-(cellY-mCurY)) * mMapWidgetSize); + widgetPos = MyGUI::IntPoint(static_cast(nX * mMapWidgetSize + (1 + (cellX - mCurX)) * mMapWidgetSize), + static_cast(nY * mMapWidgetSize + (1-(cellY-mCurY)) * mMapWidgetSize)); } markerPos.nX = nX; @@ -309,8 +309,8 @@ namespace MWGui markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote)); - markerWidget->setNormalColour(MyGUI::Colour(1.0,0.3,0.3)); - markerWidget->setHoverColour(MyGUI::Colour(1.0,0.5,0.5)); + markerWidget->setNormalColour(MyGUI::Colour(1.0f, 0.3f, 0.3f)); + markerWidget->setHoverColour(MyGUI::Colour(1.0f, 0.5f, 0.5f)); markerWidget->setUserData(marker); markerWidget->setNeedMouseFocus(true); customMarkerCreated(markerWidget); @@ -424,7 +424,7 @@ namespace MWGui void LocalMapBase::setPlayerPos(int cellX, int cellY, const float nx, const float ny) { - MyGUI::IntPoint pos(mMapWidgetSize+nx*mMapWidgetSize-16, mMapWidgetSize+ny*mMapWidgetSize-16); + MyGUI::IntPoint pos(static_cast(mMapWidgetSize + nx*mMapWidgetSize - 16), static_cast(mMapWidgetSize + ny*mMapWidgetSize - 16)); pos.left += (cellX - mCurX) * mMapWidgetSize; pos.top -= (cellY - mCurY) * mMapWidgetSize; @@ -435,7 +435,7 @@ namespace MWGui mCompass->setPosition(pos); MyGUI::IntPoint middle (pos.left+16, pos.top+16); MyGUI::IntCoord viewsize = mLocalMap->getCoord(); - MyGUI::IntPoint viewOffset(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top); + MyGUI::IntPoint viewOffset((viewsize.width / 2) - middle.left, (viewsize.height / 2) - middle.top); mLocalMap->setViewOffset(viewOffset); } } @@ -668,7 +668,7 @@ namespace MWGui else { worldPos.x = (x + nX) * cellSize; - worldPos.y = (y + (1.0-nY)) * cellSize; + worldPos.y = (y + (1.0f-nY)) * cellSize; } mEditingMarker.mWorldX = worldPos.x; @@ -737,8 +737,8 @@ namespace MWGui int markerSize = 12; int offset = mGlobalMapRender->getCellSize()/2 - markerSize/2; MyGUI::IntCoord widgetCoord( - worldX * mGlobalMapRender->getWidth()+offset, - worldY * mGlobalMapRender->getHeight()+offset, + static_cast(worldX * mGlobalMapRender->getWidth()+offset), + static_cast(worldY * mGlobalMapRender->getHeight() + offset), markerSize, markerSize); MyGUI::Widget* markerWidget = mGlobalMap->createWidget("MarkerButton", @@ -827,18 +827,7 @@ namespace MWGui if (MWBase::Environment::get().getWorld ()->isCellExterior ()) { Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayerPtr().getRefData ().getBaseNode ()->_getDerivedPosition (); - - float worldX, worldY; - mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY); - worldX *= mGlobalMapRender->getWidth(); - worldY *= mGlobalMapRender->getHeight(); - - mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16)); - - // set the view offset so that player is in the center - MyGUI::IntSize viewsize = mGlobalMap->getSize(); - MyGUI::IntPoint viewoffs(0.5*viewsize.width - worldX, 0.5*viewsize.height - worldY); - mGlobalMap->setViewOffset(viewoffs); + setGlobalMapPlayerPosition(pos.x, pos.y); } } @@ -854,11 +843,11 @@ namespace MWGui x *= mGlobalMapRender->getWidth(); y *= mGlobalMapRender->getHeight(); - mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(x - 16, y - 16)); + mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(static_cast(x - 16), static_cast(y - 16))); // set the view offset so that player is in the center MyGUI::IntSize viewsize = mGlobalMap->getSize(); - MyGUI::IntPoint viewoffs(0.5*viewsize.width - x, 0.5*viewsize.height - y); + MyGUI::IntPoint viewoffs(static_cast(viewsize.width * 0.5f - x), static_cast(viewsize.height *0.5 - y)); mGlobalMap->setViewOffset(viewoffs); } diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 907c664b1a..4407bf9277 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -59,11 +59,11 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get() .find("fRepairMult")->getFloat(); - float p = std::max(1, basePrice); - float r = std::max(1, static_cast(maxDurability / p)); + float p = static_cast(std::max(1, basePrice)); + float r = static_cast(std::max(1, static_cast(maxDurability / p))); - int x = ((maxDurability - durability) / r); - x = (fRepairMult * x); + int x = static_cast((maxDurability - durability) / r); + x = static_cast(fRepairMult * x); int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); @@ -105,10 +105,10 @@ void MerchantRepair::startRepair(const MWWorld::Ptr &actor) void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mList->getViewOffset().top + _rel*0.3 > 0) + if (mList->getViewOffset().top + _rel*0.3f > 0) mList->setViewOffset(MyGUI::IntPoint(0, 0)); else - mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3)); + mList->setViewOffset(MyGUI::IntPoint(0, static_cast(mList->getViewOffset().top + _rel*0.3f))); } void MerchantRepair::open() diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index cdbcf784df..b7c67e68bf 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -70,7 +70,7 @@ namespace MWGui it = mMessageBoxes.begin(); while(it != mMessageBoxes.end()) { - (*it)->update(height); + (*it)->update(static_cast(height)); height += (*it)->getHeight(); ++it; } diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index f6882ada61..bc7c5528e8 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -1,5 +1,7 @@ #include "pickpocketitemmodel.hpp" +#include + #include "../mwmechanics/npcstats.hpp" #include "../mwworld/class.hpp" @@ -12,11 +14,13 @@ namespace MWGui int chance = thief.getClass().getSkill(thief, ESM::Skill::Sneak); mSourceModel->update(); + + // build list of items that player is unable to find when attempts to pickpocket. if (hideItems) { for (size_t i = 0; igetItemCount(); ++i) { - if (std::rand() / static_cast(RAND_MAX) * 100 > chance) + if (chance <= OEngine::Misc::Rng::roll0to99()) mHiddenItems.push_back(mSourceModel->getItem(i)); } } diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index a102de1e56..834c156f92 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -94,12 +94,24 @@ namespace MWGui while (key->getChildCount()) // Destroy number label MyGUI::Gui::getInstance().destroyWidget(key->getChildAt(0)); - mAssigned[index] = Type_Unassigned; + if (index == 9) + { + mAssigned[index] = Type_HandToHand; - MyGUI::TextBox* textBox = key->createWidgetReal("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default); - textBox->setTextAlign (MyGUI::Align::Center); - textBox->setCaption (MyGUI::utility::toString(index+1)); - textBox->setNeedMouseFocus (false); + MyGUI::ImageBox* image = key->createWidget("ImageBox", + MyGUI::IntCoord(14, 13, 32, 32), MyGUI::Align::Default); + image->setImageTexture("icons\\k\\stealth_handtohand.dds"); + image->setNeedMouseFocus(false); + } + else + { + mAssigned[index] = Type_Unassigned; + + MyGUI::TextBox* textBox = key->createWidgetReal("SandText", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Default); + textBox->setTextAlign (MyGUI::Align::Center); + textBox->setCaption (MyGUI::utility::toString(index+1)); + textBox->setNeedMouseFocus (false); + } } void QuickKeysMenu::onQuickKeyButtonClicked(MyGUI::Widget* sender) @@ -338,6 +350,11 @@ namespace MWGui store.setSelectedEnchantItem(it); MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell); } + else if (type == Type_HandToHand) + { + store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player); + MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon); + } } // --------------------------------------------------------------------------------------------------------- @@ -409,6 +426,7 @@ namespace MWGui switch (type) { case Type_Unassigned: + case Type_HandToHand: break; case Type_Item: case Type_MagicItem: @@ -489,6 +507,7 @@ namespace MWGui break; } case Type_Unassigned: + case Type_HandToHand: unassign(button, i); break; } @@ -529,7 +548,6 @@ namespace MWGui WindowModal::open(); mMagicList->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); - mMagicList->update(); } void MagicSelectionDialog::onModelIndexSelected(SpellModel::ModelIndex index) diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 00afa45610..afbcff001e 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -37,15 +37,16 @@ namespace MWGui void activateQuickKey(int index); + /// @note This enum is serialized, so don't move the items around! enum QuickKeyType { Type_Item, Type_Magic, Type_MagicItem, - Type_Unassigned + Type_Unassigned, + Type_HandToHand }; - void write (ESM::ESMWriter& writer); void readRecord (ESM::ESMReader& reader, uint32_t type); void clear(); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index b03bf758af..f908a9dd0d 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -142,13 +142,13 @@ namespace MWGui for (unsigned int i=0; igetScrollRange()-1) - 0.5) * 3.14 * 2; + float angle = (float(_position) / (scroll->getScrollRange()-1) - 0.5f) * 3.14f * 2; mPreview->update (angle); mPreviewDirty = true; mCurrentAngle = angle; @@ -404,7 +404,7 @@ namespace MWGui skillWidget = mSkillList->createWidget("MW_StatNameValue", coord1, MyGUI::Align::Default, std::string("Skill") + MyGUI::utility::toString(i)); skillWidget->setSkillNumber(skillId); - skillWidget->setSkillValue(Widgets::MWSkill::SkillValue(race->mData.mBonus[i].mBonus)); + skillWidget->setSkillValue(Widgets::MWSkill::SkillValue(static_cast(race->mData.mBonus[i].mBonus))); ToolTips::createSkillToolTip(skillWidget, skillId); diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 2c854a8f54..a0e5991b46 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include "../mwbase/world.hpp" @@ -119,7 +121,7 @@ void Recharge::updateView() Widgets::MWDynamicStatPtr chargeWidget = mView->createWidget ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default); - chargeWidget->setValue(iter->getCellRef().getEnchantmentCharge(), enchantment->mData.mCharge); + chargeWidget->setValue(static_cast(iter->getCellRef().getEnchantmentCharge()), enchantment->mData.mCharge); chargeWidget->setNeedMouseFocus(false); currentY += 32 + 4; @@ -149,11 +151,11 @@ void Recharge::onItemClicked(MyGUI::Widget *sender) MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player); - float luckTerm = 0.1 * stats.getAttribute(ESM::Attribute::Luck).getModified(); + float luckTerm = 0.1f * stats.getAttribute(ESM::Attribute::Luck).getModified(); if (luckTerm < 1|| luckTerm > 10) luckTerm = 1; - float intelligenceTerm = 0.2 * stats.getAttribute(ESM::Attribute::Intelligence).getModified(); + float intelligenceTerm = 0.2f * stats.getAttribute(ESM::Attribute::Intelligence).getModified(); if (intelligenceTerm > 20) intelligenceTerm = 20; @@ -161,7 +163,7 @@ void Recharge::onItemClicked(MyGUI::Widget *sender) intelligenceTerm = 1; float x = (npcStats.getSkill(ESM::Skill::Enchant).getModified() + intelligenceTerm + luckTerm) * stats.getFatigueTerm(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] + int roll = OEngine::Misc::Rng::roll0to99(); if (roll < x) { std::string soul = gem.getCellRef().getSoul(); @@ -197,10 +199,10 @@ void Recharge::onItemClicked(MyGUI::Widget *sender) void Recharge::onMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mView->getViewOffset().top + _rel*0.3 > 0) + if (mView->getViewOffset().top + _rel*0.3f > 0) mView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mView->setViewOffset(MyGUI::IntPoint(0, mView->getViewOffset().top + _rel*0.3)); + mView->setViewOffset(MyGUI::IntPoint(0, static_cast(mView->getViewOffset().top + _rel*0.3f))); } } diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index c3c9714005..9f26923d44 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -150,10 +150,10 @@ void Repair::onRepairItem(MyGUI::Widget *sender) void Repair::onMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mRepairView->getViewOffset().top + _rel*0.3 > 0) + if (mRepairView->getViewOffset().top + _rel*0.3f > 0) mRepairView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mRepairView->setViewOffset(MyGUI::IntPoint(0, mRepairView->getViewOffset().top + _rel*0.3)); + mRepairView->setViewOffset(MyGUI::IntPoint(0, static_cast(mRepairView->getViewOffset().top + _rel*0.3f))); } } diff --git a/apps/openmw/mwgui/review.cpp b/apps/openmw/mwgui/review.cpp index 1bcd2d31aa..47c7cef219 100644 --- a/apps/openmw/mwgui/review.cpp +++ b/apps/openmw/mwgui/review.cpp @@ -146,21 +146,21 @@ namespace MWGui void ReviewDialog::setHealth(const MWMechanics::DynamicStat& value) { - mHealth->setValue(value.getCurrent(), value.getModified()); + mHealth->setValue(static_cast(value.getCurrent()), static_cast(value.getModified())); std::string valStr = MyGUI::utility::toString(value.getCurrent()) + "/" + MyGUI::utility::toString(value.getModified()); mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } void ReviewDialog::setMagicka(const MWMechanics::DynamicStat& value) { - mMagicka->setValue(value.getCurrent(), value.getModified()); + mMagicka->setValue(static_cast(value.getCurrent()), static_cast(value.getModified())); std::string valStr = MyGUI::utility::toString(value.getCurrent()) + "/" + MyGUI::utility::toString(value.getModified()); mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } void ReviewDialog::setFatigue(const MWMechanics::DynamicStat& value) { - mFatigue->setValue(value.getCurrent(), value.getModified()); + mFatigue->setValue(static_cast(value.getCurrent()), static_cast(value.getModified())); std::string valStr = MyGUI::utility::toString(value.getCurrent()) + "/" + MyGUI::utility::toString(value.getModified()); mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } @@ -180,7 +180,7 @@ namespace MWGui MyGUI::TextBox* widget = mSkillWidgetMap[skillId]; if (widget) { - float modified = value.getModified(), base = value.getBase(); + float modified = static_cast(value.getModified()), base = static_cast(value.getBase()); std::string text = MyGUI::utility::toString(std::floor(modified)); std::string state = "normal"; if (modified > base) @@ -376,7 +376,7 @@ namespace MWGui if (mSkillView->getViewOffset().top + _rel*0.3 > 0) mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); + mSkillView->setViewOffset(MyGUI::IntPoint(0, static_cast(mSkillView->getViewOffset().top + _rel*0.3))); } } diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index 11470a20f3..2192adbdec 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -6,7 +6,7 @@ namespace MWState { class Character; - class Slot; + struct Slot; } namespace MWGui diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index d61693d39e..85d1c8c4ee 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -48,7 +48,7 @@ namespace MWGui center(); } - void ScrollWindow::open (MWWorld::Ptr scroll) + void ScrollWindow::open (MWWorld::Ptr scroll, bool showTakeButton) { // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); @@ -71,7 +71,7 @@ namespace MWGui mTextView->setViewOffset(MyGUI::IntPoint(0,0)); - setTakeButtonShow(true); + setTakeButtonShow(showTakeButton); } void ScrollWindow::exit() diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index e1f86529a3..3c9e718b61 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -17,14 +17,14 @@ namespace MWGui public: ScrollWindow (); - void open (MWWorld::Ptr scroll); + void open (MWWorld::Ptr scroll, bool showTakeButton); virtual void exit(); - void setTakeButtonShow(bool show); void setInventoryAllowed(bool allowed); protected: void onCloseButtonClicked (MyGUI::Widget* _sender); void onTakeButtonClicked (MyGUI::Widget* _sender); + void setTakeButtonShow(bool show); private: Gui::ImageButton* mCloseButton; diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index a4f87e598b..d895a28ea7 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -148,11 +148,11 @@ namespace MWGui value = std::max(min, std::min(value, max)); value = (value-min)/(max-min); - scroll->setScrollPosition( value * (scroll->getScrollRange()-1)); + scroll->setScrollPosition(static_cast(value * (scroll->getScrollRange() - 1))); } else { - int value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current)); + int value = Settings::Manager::getInt(getSettingName(current), getSettingCategory(current)); scroll->setScrollPosition(value); } scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); @@ -163,7 +163,8 @@ namespace MWGui } SettingsWindow::SettingsWindow() : - WindowBase("openmw_settings_window.layout") + WindowBase("openmw_settings_window.layout"), + mKeyboardMode(true) { configureWidgets(mMainWidget); @@ -188,6 +189,8 @@ namespace MWGui getWidget(mResetControlsButton, "ResetControlsButton"); getWidget(mRefractionButton, "RefractionButton"); getWidget(mDifficultySlider, "DifficultySlider"); + getWidget(mKeyboardSwitch, "KeyboardButton"); + getWidget(mControllerSwitch, "ControllerButton"); #ifndef WIN32 // hide gamma controls since it currently does not work under Linux @@ -213,6 +216,9 @@ namespace MWGui mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged); + mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked); + mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked); + center(); mResetControlsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindings); @@ -260,9 +266,13 @@ namespace MWGui MyGUI::TextBox* diffText; getWidget(diffText, "DifficultyText"); + diffText->setCaptionWithReplacing("#{sDifficulty} (" + MyGUI::utility::toString(int(Settings::Manager::getInt("difficulty", "Game"))) + ")"); mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video")); + + mKeyboardSwitch->setStateSelected(true); + mControllerSwitch->setStateSelected(false); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -462,14 +472,37 @@ namespace MWGui MWBase::Environment::get().getInputManager()->processChangedSettings(changed); } + void SettingsWindow::onKeyboardSwitchClicked(MyGUI::Widget* _sender) + { + if(mKeyboardMode) + return; + mKeyboardMode = true; + mKeyboardSwitch->setStateSelected(true); + mControllerSwitch->setStateSelected(false); + updateControlsBox(); + } + + void SettingsWindow::onControllerSwitchClicked(MyGUI::Widget* _sender) + { + if(!mKeyboardMode) + return; + mKeyboardMode = false; + mKeyboardSwitch->setStateSelected(false); + mControllerSwitch->setStateSelected(true); + updateControlsBox(); + } + void SettingsWindow::updateControlsBox() { while (mControlsBox->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(mControlsBox->getChildAt(0)); - MWBase::Environment::get().getWindowManager ()->removeStaticMessageBox(); - - std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); + MWBase::Environment::get().getWindowManager()->removeStaticMessageBox(); + std::vector actions; + if(mKeyboardMode) + actions = MWBase::Environment::get().getInputManager()->getActionKeySorting(); + else + actions = MWBase::Environment::get().getInputManager()->getActionControllerSorting(); const int h = 18; const int w = mControlsBox->getWidth() - 28; @@ -480,7 +513,11 @@ namespace MWGui if (desc == "") continue; - std::string binding = MWBase::Environment::get().getInputManager()->getActionBindingName (*it); + std::string binding; + if(mKeyboardMode) + binding = MWBase::Environment::get().getInputManager()->getActionKeyBindingName(*it); + else + binding = MWBase::Environment::get().getInputManager()->getActionControllerBindingName(*it); Gui::SharedStateButton* leftText = mControlsBox->createWidget("SandTextButton", MyGUI::IntCoord(0,curH,w,h), MyGUI::Align::Default); leftText->setCaptionWithReplacing(desc); @@ -514,16 +551,16 @@ namespace MWGui MWBase::Environment::get().getWindowManager ()->staticMessageBox ("#{sControlsMenu3}"); MWBase::Environment::get().getWindowManager ()->disallowMouse(); - MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId); + MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId, mKeyboardMode); } void SettingsWindow::onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mControlsBox->getViewOffset().top + _rel*0.3 > 0) + if (mControlsBox->getViewOffset().top + _rel*0.3f > 0) mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0)); else - mControlsBox->setViewOffset(MyGUI::IntPoint(0, mControlsBox->getViewOffset().top + _rel*0.3)); + mControlsBox->setViewOffset(MyGUI::IntPoint(0, static_cast(mControlsBox->getViewOffset().top + _rel*0.3f))); } void SettingsWindow::onResetDefaultBindings(MyGUI::Widget* _sender) @@ -537,7 +574,10 @@ namespace MWGui void SettingsWindow::onResetDefaultBindingsAccept() { - MWBase::Environment::get().getInputManager ()->resetToDefaultBindings (); + if(mKeyboardMode) + MWBase::Environment::get().getInputManager ()->resetToDefaultKeyBindings (); + else + MWBase::Environment::get().getInputManager()->resetToDefaultControllerBindings(); updateControlsBox (); } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 8dcc8dd077..1b970b8de5 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -46,6 +46,9 @@ namespace MWGui // controls MyGUI::ScrollView* mControlsBox; MyGUI::Button* mResetControlsButton; + MyGUI::Button* mKeyboardSwitch; + MyGUI::Button* mControllerSwitch; + bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); @@ -63,6 +66,8 @@ namespace MWGui void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel); void onResetDefaultBindings(MyGUI::Widget* _sender); void onResetDefaultBindingsAccept (); + void onKeyboardSwitchClicked(MyGUI::Widget* _sender); + void onControllerSwitchClicked(MyGUI::Widget* _sender); void onWindowResize(MyGUI::Window* _sender); diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 54094b6062..57b02940e1 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -46,7 +46,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->getStore(); const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId); - int price = spell->mData.mCost*store.get().find("fSpellValueMult")->getFloat(); + int price = static_cast(spell->mData.mCost*store.get().find("fSpellValueMult")->getFloat()); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -187,7 +187,7 @@ namespace MWGui if (mSpellsView->getViewOffset().top + _rel*0.3 > 0) mSpellsView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mSpellsView->setViewOffset(MyGUI::IntPoint(0, mSpellsView->getViewOffset().top + _rel*0.3)); + mSpellsView->setViewOffset(MyGUI::IntPoint(0, static_cast(mSpellsView->getViewOffset().top + _rel*0.3f))); } } diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index f4c9d021a5..c744d3ed63 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -114,7 +114,7 @@ namespace MWGui void EditEffectDialog::newEffect (const ESM::MagicEffect *effect) { - bool allowSelf = effect->mData.mFlags & ESM::MagicEffect::CastSelf; + bool allowSelf = (effect->mData.mFlags & ESM::MagicEffect::CastSelf) != 0; bool allowTouch = (effect->mData.mFlags & ESM::MagicEffect::CastTouch) && !mConstantEffect; bool allowTarget = (effect->mData.mFlags & ESM::MagicEffect::CastTarget) && !mConstantEffect; @@ -226,7 +226,7 @@ namespace MWGui // cycle through range types until we find something that's allowed // does not handle the case where nothing is allowed (this should be prevented before opening the Add Effect dialog) - bool allowSelf = mMagicEffect->mData.mFlags & ESM::MagicEffect::CastSelf; + bool allowSelf = (mMagicEffect->mData.mFlags & ESM::MagicEffect::CastSelf) != 0; bool allowTouch = (mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTouch) && !mConstantEffect; bool allowTarget = (mMagicEffect->mData.mFlags & ESM::MagicEffect::CastTarget) && !mConstantEffect; if (mEffect.mRange == ESM::RT_Self && !allowSelf) @@ -440,14 +440,14 @@ namespace MWGui for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) { - float x = 0.5 * (it->mMagnMin + it->mMagnMax); + float x = 0.5f * (it->mMagnMin + it->mMagnMax); const ESM::MagicEffect* effect = store.get().find(it->mEffectID); - x *= 0.1 * effect->mData.mBaseCost; + x *= 0.1f * effect->mData.mBaseCost; x *= 1 + it->mDuration; - x += 0.05 * std::max(1, it->mArea) * effect->mData.mBaseCost; + x += 0.05f * std::max(1, it->mArea) * effect->mData.mBaseCost; float fEffectCostMult = store.get().find("fEffectCostMult")->getFloat(); @@ -471,7 +471,7 @@ namespace MWGui float fSpellMakingValueMult = store.get().find("fSpellMakingValueMult")->getFloat(); - int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,int(y) * fSpellMakingValueMult,true); + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, static_cast(y * fSpellMakingValueMult),true); mPriceLabel->setCaption(MyGUI::utility::toString(int(price))); diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 20c6f3ba83..c597cfaebe 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -30,7 +30,7 @@ namespace MWGui { MagicEffectInfo newEffectSource; newEffectSource.mKey = key; - newEffectSource.mMagnitude = magnitude; + newEffectSource.mMagnitude = static_cast(magnitude); newEffectSource.mPermanent = mIsPermanent; newEffectSource.mRemainingTime = remainingTime; newEffectSource.mSource = sourceName; diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index 4713720cd0..91512a0116 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -103,7 +103,7 @@ namespace MWGui && item.getClass().canBeEquipped(item, mActor).first == 0) continue; - int castCost = MWMechanics::getEffectiveEnchantmentCastCost(enchant->mData.mCost, mActor); + int castCost = MWMechanics::getEffectiveEnchantmentCastCost(static_cast(enchant->mData.mCost), mActor); std::string cost = boost::lexical_cast(castCost); int currentCharge = int(item.getCellRef().getEnchantmentCharge()); diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp index 1c17a11f66..a7c1d781bd 100644 --- a/apps/openmw/mwgui/spellview.cpp +++ b/apps/openmw/mwgui/spellview.cpp @@ -10,6 +10,16 @@ namespace MWGui { + const char* SpellView::sSpellModelIndex = "SpellModelIndex"; + + SpellView::LineInfo::LineInfo(MyGUI::Widget* leftWidget, MyGUI::Widget* rightWidget, SpellModel::ModelIndex spellIndex) + : mLeftWidget(leftWidget) + , mRightWidget(rightWidget) + , mSpellIndex(spellIndex) + { + + } + SpellView::SpellView() : mShowCostColumn(true) , mHighlightSelected(true) @@ -113,10 +123,10 @@ namespace MWGui group.push_back(costChance); Gui::SharedStateButton::createButtonGroup(group); - mLines.push_back(std::make_pair(t, costChance)); + mLines.push_back(LineInfo(t, costChance, i)); } else - mLines.push_back(std::make_pair(t, (MyGUI::Widget*)NULL)); + mLines.push_back(LineInfo(t, (MyGUI::Widget*)NULL, i)); t->setStateSelected(spell.mSelected); } @@ -124,30 +134,85 @@ namespace MWGui layoutWidgets(); } + void SpellView::incrementalUpdate() + { + if (!mModel.get()) + { + return; + } + + mModel->update(); + bool fullUpdateRequired = false; + SpellModel::ModelIndex maxSpellIndexFound = -1; + for (std::vector< LineInfo >::iterator it = mLines.begin(); it != mLines.end(); ++it) + { + // only update the lines that are "updateable" + SpellModel::ModelIndex spellIndex(it->mSpellIndex); + if (spellIndex != NoSpellIndex) + { + Gui::SharedStateButton* nameButton = reinterpret_cast(it->mLeftWidget); + + // match model against line + // if don't match, then major change has happened, so do a full update + if (mModel->getItemCount() <= static_cast(spellIndex)) + { + fullUpdateRequired = true; + break; + } + + // more checking for major change. + const Spell& spell = mModel->getItem(spellIndex); + if (nameButton->getCaption() != spell.mName) + { + fullUpdateRequired = true; + break; + } + else + { + maxSpellIndexFound = spellIndex; + Gui::SharedStateButton* costButton = reinterpret_cast(it->mRightWidget); + if ((costButton != NULL) && (costButton->getCaption() != spell.mCostColumn)) + { + costButton->setCaption(spell.mCostColumn); + } + } + } + } + + // special case, look for spells added to model that are beyond last updatable item + SpellModel::ModelIndex topSpellIndex = mModel->getItemCount() - 1; + if (fullUpdateRequired || + ((0 <= topSpellIndex) && (maxSpellIndexFound < topSpellIndex))) + { + update(); + } + } + + void SpellView::layoutWidgets() { int height = 0; - for (std::vector< std::pair >::iterator it = mLines.begin(); + for (std::vector< LineInfo >::iterator it = mLines.begin(); it != mLines.end(); ++it) { - height += (it->first)->getHeight(); + height += (it->mLeftWidget)->getHeight(); } bool scrollVisible = height > mScrollView->getHeight(); int width = mScrollView->getWidth() - (scrollVisible ? 18 : 0); height = 0; - for (std::vector< std::pair >::iterator it = mLines.begin(); + for (std::vector< LineInfo >::iterator it = mLines.begin(); it != mLines.end(); ++it) { - int lineHeight = (it->first)->getHeight(); - (it->first)->setCoord(4, height, width-8, lineHeight); - if (it->second) + int lineHeight = (it->mLeftWidget)->getHeight(); + (it->mLeftWidget)->setCoord(4, height, width - 8, lineHeight); + if (it->mRightWidget) { - (it->second)->setCoord(4, height, width-8, lineHeight); - MyGUI::TextBox* second = (it->second)->castType(false); + (it->mRightWidget)->setCoord(4, height, width - 8, lineHeight); + MyGUI::TextBox* second = (it->mRightWidget)->castType(false); if (second) - (it->first)->setSize(width-8-second->getTextSize().width, lineHeight); + (it->mLeftWidget)->setSize(width - 8 - second->getTextSize().width, lineHeight); } height += lineHeight; @@ -167,7 +232,7 @@ namespace MWGui MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 18), MyGUI::Align::Left | MyGUI::Align::Top); separator->setNeedMouseFocus(false); - mLines.push_back(std::make_pair(separator, (MyGUI::Widget*)NULL)); + mLines.push_back(LineInfo(separator, (MyGUI::Widget*)NULL, NoSpellIndex)); } MyGUI::TextBox* groupWidget = mScrollView->createWidget("SandBrightText", @@ -186,10 +251,10 @@ namespace MWGui groupWidget2->setTextAlign(MyGUI::Align::Right); groupWidget2->setNeedMouseFocus(false); - mLines.push_back(std::make_pair(groupWidget, groupWidget2)); + mLines.push_back(LineInfo(groupWidget, groupWidget2, NoSpellIndex)); } else - mLines.push_back(std::make_pair(groupWidget, (MyGUI::Widget*)NULL)); + mLines.push_back(LineInfo(groupWidget, (MyGUI::Widget*)NULL, NoSpellIndex)); } @@ -222,24 +287,28 @@ namespace MWGui widget->setUserString("Spell", spell.mId); } - widget->setUserString("SpellModelIndex", MyGUI::utility::toString(index)); + widget->setUserString(sSpellModelIndex, MyGUI::utility::toString(index)); widget->eventMouseWheel += MyGUI::newDelegate(this, &SpellView::onMouseWheel); widget->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellView::onSpellSelected); } + SpellModel::ModelIndex SpellView::getSpellModelIndex(MyGUI::Widget* widget) + { + return MyGUI::utility::parseInt(widget->getUserString(sSpellModelIndex)); + } + void SpellView::onSpellSelected(MyGUI::Widget* _sender) { - SpellModel::ModelIndex i = MyGUI::utility::parseInt(_sender->getUserString("SpellModelIndex")); - eventSpellClicked(i); + eventSpellClicked(getSpellModelIndex(_sender)); } void SpellView::onMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mScrollView->getViewOffset().top + _rel*0.3 > 0) + if (mScrollView->getViewOffset().top + _rel*0.3f > 0) mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3)); + mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast(mScrollView->getViewOffset().top + _rel*0.3f))); } } diff --git a/apps/openmw/mwgui/spellview.hpp b/apps/openmw/mwgui/spellview.hpp index 005d206f4d..7af1bda7a7 100644 --- a/apps/openmw/mwgui/spellview.hpp +++ b/apps/openmw/mwgui/spellview.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_GUI_SPELLVIEW_H #define OPENMW_GUI_SPELLVIEW_H +#include + #include #include "spellmodel.hpp" @@ -37,6 +39,9 @@ namespace MWGui void update(); + /// simplified update called each frame + void incrementalUpdate(); + typedef MyGUI::delegates::CMultiDelegate1 EventHandle_ModelIndex; /// Fired when a spell was clicked EventHandle_ModelIndex eventSpellClicked; @@ -51,7 +56,25 @@ namespace MWGui std::auto_ptr mModel; - std::vector< std::pair > mLines; + /// tracks a row in the spell view + struct LineInfo + { + /// the widget on the left side of the row + MyGUI::Widget* mLeftWidget; + + /// the widget on the left side of the row (if there is one) + MyGUI::Widget* mRightWidget; + + /// index to item in mModel that row is showing information for + SpellModel::ModelIndex mSpellIndex; + + LineInfo(MyGUI::Widget* leftWidget, MyGUI::Widget* rightWidget, SpellModel::ModelIndex spellIndex); + }; + + /// magic number indicating LineInfo does not correspond to an item in mModel + enum { NoSpellIndex = -1 }; + + std::vector< LineInfo > mLines; bool mShowCostColumn; bool mHighlightSelected; @@ -62,6 +85,10 @@ namespace MWGui void onSpellSelected(MyGUI::Widget* _sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); + + SpellModel::ModelIndex getSpellModelIndex(MyGUI::Widget* _sender); + + static const char* sSpellModelIndex; }; } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index cc032691e2..ca5ec20bdf 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -28,6 +28,7 @@ namespace MWGui : WindowPinnableBase("openmw_spell_window.layout") , NoDrop(drag, mMainWidget) , mSpellView(NULL) + , mUpdateTimer(0.0f) { mSpellIcons = new SpellIcons(); @@ -60,12 +61,25 @@ namespace MWGui updateSpells(); } + void SpellWindow::onFrame(float dt) + { + if (mMainWidget->getVisible()) + { + NoDrop::onFrame(dt); + mUpdateTimer += dt; + if (0.5f < mUpdateTimer) + { + mUpdateTimer = 0; + mSpellView->incrementalUpdate(); + } + } + } + void SpellWindow::updateSpells() { mSpellIcons->updateWidgets(mEffectBox, false); mSpellView->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); - mSpellView->update(); } void SpellWindow::onEnchantedItemSelected(MWWorld::Ptr item, bool alreadyEquipped) @@ -170,7 +184,6 @@ namespace MWGui void SpellWindow::cycle(bool next) { mSpellView->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); - mSpellView->getModel()->update(); SpellModel::ModelIndex selected = 0; for (SpellModel::ModelIndex i = 0; igetModel()->getItemCount()); ++i) diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 8b5474f58c..dcce10f9da 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -19,7 +19,7 @@ namespace MWGui void updateSpells(); - void onFrame(float dt) { NoDrop::onFrame(dt); } + void onFrame(float dt); /// Cycle to next/previous spell void cycle(bool next); @@ -41,6 +41,9 @@ namespace MWGui SpellView* mSpellView; SpellIcons* mSpellIcons; + + private: + float mUpdateTimer; }; } diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 2a22f42393..cb1bf6f371 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -80,13 +80,13 @@ namespace MWGui if (mSkillView->getViewOffset().top + _rel*0.3 > 0) mSkillView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mSkillView->setViewOffset(MyGUI::IntPoint(0, mSkillView->getViewOffset().top + _rel*0.3)); + mSkillView->setViewOffset(MyGUI::IntPoint(0, static_cast(mSkillView->getViewOffset().top + _rel*0.3))); } void StatsWindow::onWindowResize(MyGUI::Window* window) { - mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) ); - mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) ); + mLeftPane->setCoord( MyGUI::IntCoord(0, 0, static_cast(0.44*window->getSize().width), window->getSize().height) ); + mRightPane->setCoord( MyGUI::IntCoord(static_cast(0.44*window->getSize().width), 0, static_cast(0.56*window->getSize().width), window->getSize().height) ); // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden mSkillView->setVisibleVScroll(false); mSkillView->setCanvasSize (mSkillView->getWidth(), mSkillView->getCanvasSize().height); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 2c10004a63..4e03b788a4 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -308,7 +308,7 @@ namespace MWGui void ToolTips::position(MyGUI::IntPoint& position, MyGUI::IntSize size, MyGUI::IntSize viewportSize) { position += MyGUI::IntPoint(0, 32) - - MyGUI::IntPoint((MyGUI::InputManager::getInstance().getMousePosition().left / float(viewportSize.width) * size.width), 0); + - MyGUI::IntPoint(static_cast(MyGUI::InputManager::getInstance().getMousePosition().left / float(viewportSize.width) * size.width), 0); if ((position.left + size.width) > viewportSize.width) { @@ -413,7 +413,7 @@ namespace MWGui { MyGUI::ImageBox* icon = mDynamicToolTipBox->createWidget("MarkerButton", MyGUI::IntCoord(padding.left, totalSize.height+padding.top, 8, 8), MyGUI::Align::Default); - icon->setColour(MyGUI::Colour(1.0,0.3,0.3)); + icon->setColour(MyGUI::Colour(1.0f, 0.3f, 0.3f)); MyGUI::EditBox* edit = mDynamicToolTipBox->createWidget("SandText", MyGUI::IntCoord(padding.left+8+4, totalSize.height+padding.top, 300-padding.left-8-4, 300-totalSize.height), MyGUI::Align::Default); diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 4bd4d88aa2..71b4a560f5 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -9,7 +9,7 @@ namespace ESM { - class Class; + struct Class; struct Race; } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 40cf3e9bf7..42491a5e87 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include "../mwbase/environment.hpp" @@ -34,18 +36,21 @@ namespace int getEffectiveValue (MWWorld::Ptr item, int count) { - int price = item.getClass().getValue(item) * count; + float price = static_cast(item.getClass().getValue(item)); if (item.getClass().hasItemHealth(item)) - price *= (static_cast(item.getClass().getItemHealth(item)) / item.getClass().getItemMaxHealth(item)); - return price; + { + price *= item.getClass().getItemHealth(item); + price /= item.getClass().getItemMaxHealth(item); + } + return static_cast(price * count); } } namespace MWGui { - const float TradeWindow::sBalanceChangeInitialPause = 0.5; - const float TradeWindow::sBalanceChangeInterval = 0.1; + const float TradeWindow::sBalanceChangeInitialPause = 0.5f; + const float TradeWindow::sBalanceChangeInterval = 0.1f; TradeWindow::TradeWindow() : WindowBase("openmw_trade_window.layout") @@ -340,16 +345,16 @@ namespace MWGui else d = int(100 * (b - a) / a); - float clampedDisposition = std::max(0,std::min(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr) - + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100)); + int clampedDisposition = std::max(0, std::min(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr) + + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100)); const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player); - float a1 = player.getClass().getSkill(player, ESM::Skill::Mercantile); + float a1 = static_cast(player.getClass().getSkill(player, ESM::Skill::Mercantile)); float b1 = 0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(); float c1 = 0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(); - float d1 = mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile); + float d1 = static_cast(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile)); float e1 = 0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(); float f1 = 0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(); @@ -362,7 +367,7 @@ namespace MWGui else x += abs(int(npcTerm - pcTerm)); - int roll = std::rand()%100 + 1; + int roll = OEngine::Misc::Rng::rollDice(100) + 1; if(roll > x || (mCurrentMerchantOffer < 0) != (mCurrentBalance < 0)) //trade refused { MWBase::Environment::get().getWindowManager()-> @@ -379,9 +384,9 @@ namespace MWGui int finalPrice = std::abs(mCurrentBalance); int initialMerchantOffer = std::abs(mCurrentMerchantOffer); if (!buying && (finalPrice > initialMerchantOffer) && finalPrice > 0) - skillGain = int(100 * (finalPrice - initialMerchantOffer) / float(finalPrice)); + skillGain = floor(100 * (finalPrice - initialMerchantOffer) / float(finalPrice)); else if (buying && (finalPrice < initialMerchantOffer) && initialMerchantOffer > 0) - skillGain = int(100 * (initialMerchantOffer - finalPrice) / float(initialMerchantOffer)); + skillGain = floor(100 * (initialMerchantOffer - finalPrice) / float(initialMerchantOffer)); player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0, skillGain); } diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 5a5f611153..6376ced574 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -40,7 +40,7 @@ namespace MWGui TrainingWindow::TrainingWindow() : WindowBase("openmw_trainingwindow.layout") , mFadeTimeRemaining(0) - , mTimeAdvancer(0.05) + , mTimeAdvancer(0.05f) { getWidget(mTrainingOptions, "TrainingOptions"); getWidget(mCancelButton, "CancelButton"); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 50e08223e4..4da1ab33a0 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -66,13 +66,13 @@ namespace MWGui if(interior) { - price = gmst.find("fMagesGuildTravel")->getFloat(); + price = gmst.find("fMagesGuildTravel")->getInt(); } else { ESM::Position PlayerPos = player.getRefData().getPosition(); float d = sqrt( pow(pos.pos[0] - PlayerPos.pos[0],2) + pow(pos.pos[1] - PlayerPos.pos[1],2) + pow(pos.pos[2] - PlayerPos.pos[2],2) ); - price = d/gmst.find("fTravelMult")->getFloat(); + price = static_cast(d / gmst.find("fTravelMult")->getFloat()); } price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); @@ -111,20 +111,26 @@ namespace MWGui mPtr = actor; clearDestinations(); - for(unsigned int i = 0;i()->mBase->mTransport.size();i++) + std::vector transport; + if (mPtr.getClass().isNpc()) + transport = mPtr.get()->mBase->getTransport(); + else if (mPtr.getTypeName() == typeid(ESM::Creature).name()) + transport = mPtr.get()->mBase->getTransport(); + + for(unsigned int i = 0;i()->mBase->mTransport[i].mCellName; + std::string cellname = transport[i].mCellName; bool interior = true; int x,y; - MWBase::Environment::get().getWorld()->positionToIndex(mPtr.get()->mBase->mTransport[i].mPos.pos[0], - mPtr.get()->mBase->mTransport[i].mPos.pos[1],x,y); + MWBase::Environment::get().getWorld()->positionToIndex(transport[i].mPos.pos[0], + transport[i].mPos.pos[1],x,y); if (cellname == "") { MWWorld::CellStore* cell = MWBase::Environment::get().getWorld()->getExterior(x,y); cellname = MWBase::Environment::get().getWorld()->getCellName(cell); interior = false; } - addDestination(cellname,mPtr.get()->mBase->mTransport[i].mPos,interior); + addDestination(cellname,transport[i].mPos,interior); } updateLabels(); @@ -209,10 +215,10 @@ namespace MWGui void TravelWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel) { - if (mDestinationsView->getViewOffset().top + _rel*0.3 > 0) + if (mDestinationsView->getViewOffset().top + _rel*0.3f > 0) mDestinationsView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mDestinationsView->setViewOffset(MyGUI::IntPoint(0, mDestinationsView->getViewOffset().top + _rel*0.3)); + mDestinationsView->setViewOffset(MyGUI::IntPoint(0, static_cast(mDestinationsView->getViewOffset().top + _rel*0.3f))); } } diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp index 0460708411..f865de377d 100644 --- a/apps/openmw/mwgui/videowidget.cpp +++ b/apps/openmw/mwgui/videowidget.cpp @@ -58,8 +58,8 @@ void VideoWidget::autoResize(bool stretch) { double imageaspect = static_cast(getVideoWidth())/getVideoHeight(); - int leftPadding = std::max(0.0, (screenSize.width - screenSize.height * imageaspect) / 2); - int topPadding = std::max(0.0, (screenSize.height - screenSize.width / imageaspect) / 2); + int leftPadding = std::max(0, static_cast(screenSize.width - screenSize.height * imageaspect) / 2); + int topPadding = std::max(0, static_cast(screenSize.height - screenSize.width / imageaspect) / 2); setCoord(leftPadding, topPadding, screenSize.width - leftPadding*2, screenSize.height - topPadding*2); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index ad873a7c3f..f74b068912 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -2,6 +2,8 @@ #include +#include + #include #include @@ -49,7 +51,7 @@ namespace MWGui WaitDialog::WaitDialog() : WindowBase("openmw_wait_dialog.layout") , mProgressBar() - , mTimeAdvancer(0.05) + , mTimeAdvancer(0.05f) , mSleeping(false) , mHours(1) , mManualHours(1) @@ -104,7 +106,7 @@ namespace MWGui mHourSlider->setScrollPosition (0); std::string month = MWBase::Environment::get().getWorld ()->getMonthName(); - int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour (); + int hour = static_cast(MWBase::Environment::get().getWorld()->getTimeStamp().getHour()); bool pm = hour >= 12; if (hour >= 13) hour -= 12; if (hour == 0) hour = 12; @@ -135,8 +137,8 @@ namespace MWGui MWBase::Environment::get().getStateManager()->quickSave("Autosave"); MWBase::World* world = MWBase::Environment::get().getWorld(); - MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.2); - mFadeTimeRemaining = 0.4; + MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.2f); + mFadeTimeRemaining = 0.4f; setVisible(false); mHours = hoursToWait; @@ -152,10 +154,9 @@ namespace MWGui const ESM::Region *region = world->getStore().get().find (regionstr); if (!region->mSleepList.empty()) { + // figure out if player will be woken while sleeping float fSleepRandMod = world->getStore().get().find("fSleepRandMod")->getFloat(); - int x = std::rand()/ (static_cast (RAND_MAX) + 1) * hoursToWait; // [0, hoursRested] - float y = fSleepRandMod * hoursToWait; - if (x > y) + if (OEngine::Misc::Rng::rollProbability() > fSleepRandMod) { float fSleepRestMod = world->getStore().get().find("fSleepRestMod")->getFloat(); mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait); @@ -251,7 +252,7 @@ namespace MWGui void WaitDialog::stopWaiting () { - MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.2); + MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.2f); mProgressBar.setVisible (false); MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Rest); MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed); diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 26fe315679..718624a16f 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -239,7 +239,7 @@ namespace MWGui params.mMagnMin = it->mMagnMin; params.mMagnMax = it->mMagnMax; params.mRange = it->mRange; - params.mIsConstant = (flags & MWEffectList::EF_Constant); + params.mIsConstant = (flags & MWEffectList::EF_Constant) != 0; params.mNoTarget = (flags & MWEffectList::EF_NoTarget); effect->setSpellEffect(params); effects.push_back(effect); @@ -540,8 +540,8 @@ namespace MWGui MWScrollBar::MWScrollBar() : mEnableRepeat(true) - , mRepeatTriggerTime(0.5) - , mRepeatStepTime(0.1) + , mRepeatTriggerTime(0.5f) + , mRepeatStepTime(0.1f) , mIsIncreasing(true) { } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index c74cff31c0..279c2f22ea 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -565,11 +565,11 @@ namespace MWGui int eff = mShown & mAllowed & ~mForceHidden; // Show the windows we want - mMap ->setVisible(eff & GW_Map); - mStatsWindow ->setVisible(eff & GW_Stats); - mInventoryWindow->setVisible(eff & GW_Inventory); + mMap ->setVisible((eff & GW_Map) != 0); + mStatsWindow ->setVisible((eff & GW_Stats) != 0); + mInventoryWindow->setVisible((eff & GW_Inventory) != 0); mInventoryWindow->setGuiMode(mode); - mSpellWindow ->setVisible(eff & GW_Magic); + mSpellWindow ->setVisible((eff & GW_Magic) != 0); break; } case GM_Container: @@ -715,16 +715,6 @@ namespace MWGui mPlayerMinorSkills = minor; } - void WindowManager::setReputation (int reputation) - { - mStatsWindow->setReputation (reputation); - } - - void WindowManager::setBounty (int bounty) - { - mStatsWindow->setBounty (bounty); - } - void WindowManager::updateSkillArea() { mStatsWindow->updateSkillArea(); @@ -1103,10 +1093,10 @@ namespace MWGui for (std::map::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it) { - MyGUI::IntPoint pos (Settings::Manager::getFloat(it->second + " x", "Windows") * x, - Settings::Manager::getFloat(it->second+ " y", "Windows") * y); - MyGUI::IntSize size (Settings::Manager::getFloat(it->second + " w", "Windows") * x, - Settings::Manager::getFloat(it->second + " h", "Windows") * y); + MyGUI::IntPoint pos(static_cast(Settings::Manager::getFloat(it->second + " x", "Windows") * x), + static_cast( Settings::Manager::getFloat(it->second+ " y", "Windows") * y)); + MyGUI::IntSize size(static_cast(Settings::Manager::getFloat(it->second + " w", "Windows") * x), + static_cast(Settings::Manager::getFloat(it->second + " h", "Windows") * y)); it->first->setPosition(pos); it->first->setSize(size); } @@ -1221,7 +1211,7 @@ namespace MWGui .find(item.getClass().getEnchantment(item)); int chargePercent = (item.getCellRef().getEnchantmentCharge() == -1) ? 100 - : (item.getCellRef().getEnchantmentCharge() / static_cast(ench->mData.mCharge) * 100); + : static_cast(item.getCellRef().getEnchantmentCharge() / static_cast(ench->mData.mCharge) * 100); mHud->setSelectedEnchantItem(item, chargePercent); mSpellWindow->setTitle(item.getClass().getName(item)); } @@ -1229,7 +1219,7 @@ namespace MWGui void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) { int durabilityPercent = - (item.getClass().getItemHealth(item) / static_cast(item.getClass().getItemMaxHealth(item)) * 100); + static_cast(item.getClass().getItemHealth(item) / static_cast(item.getClass().getItemMaxHealth(item)) * 100); mHud->setSelectedWeapon(item, durabilityPercent); mInventoryWindow->setTitle(item.getClass().getName(item)); } @@ -1262,8 +1252,8 @@ namespace MWGui void WindowManager::getMousePosition(float &x, float &y) { const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); - x = pos.left; - y = pos.top; + x = static_cast(pos.left); + y = static_cast(pos.top); const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); x /= viewSize.width; y /= viewSize.height; @@ -1287,21 +1277,14 @@ namespace MWGui } MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; } - MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; } MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } - MWGui::BookWindow* WindowManager::getBookWindow() { return mBookWindow; } - MWGui::ScrollWindow* WindowManager::getScrollWindow() { return mScrollWindow; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } - MWGui::SpellBuyingWindow* WindowManager::getSpellBuyingWindow() { return mSpellBuyingWindow; } - MWGui::TravelWindow* WindowManager::getTravelWindow() { return mTravelWindow; } - MWGui::SpellWindow* WindowManager::getSpellWindow() { return mSpellWindow; } - MWGui::Console* WindowManager::getConsole() { return mConsole; } bool WindowManager::isAllowed (GuiWindow wnd) const { - return mAllowed & wnd; + return (mAllowed & wnd) != 0; } void WindowManager::allow (GuiWindow wnd) @@ -1459,11 +1442,13 @@ namespace MWGui void WindowManager::startSpellMaking(MWWorld::Ptr actor) { + pushGuiMode(GM_SpellCreation); mSpellCreationDialog->startSpellMaking (actor); } void WindowManager::startEnchanting (MWWorld::Ptr actor) { + pushGuiMode(GM_Enchanting); mEnchantingDialog->startEnchanting (actor); } @@ -1474,16 +1459,19 @@ namespace MWGui void WindowManager::startTraining(MWWorld::Ptr actor) { + pushGuiMode(GM_Training); mTrainingWindow->startTraining(actor); } void WindowManager::startRepair(MWWorld::Ptr actor) { + pushGuiMode(GM_MerchantRepair); mMerchantRepair->startRepair(actor); } void WindowManager::startRepairItem(MWWorld::Ptr item) { + pushGuiMode(MWGui::GM_Repair); mRepair->startRepairItem(item); } @@ -1494,6 +1482,7 @@ namespace MWGui void WindowManager::showCompanionWindow(MWWorld::Ptr actor) { + pushGuiMode(MWGui::GM_Companion); mCompanionWindow->open(actor); } @@ -1569,10 +1558,10 @@ namespace MWGui void WindowManager::trackWindow(OEngine::GUI::Layout *layout, const std::string &name) { MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); - MyGUI::IntPoint pos (Settings::Manager::getFloat(name + " x", "Windows") * viewSize.width, - Settings::Manager::getFloat(name + " y", "Windows") * viewSize.height); - MyGUI::IntSize size (Settings::Manager::getFloat(name + " w", "Windows") * viewSize.width, - Settings::Manager::getFloat(name + " h", "Windows") * viewSize.height); + MyGUI::IntPoint pos(static_cast(Settings::Manager::getFloat(name + " x", "Windows") * viewSize.width), + static_cast(Settings::Manager::getFloat(name + " y", "Windows") * viewSize.height)); + MyGUI::IntSize size (static_cast(Settings::Manager::getFloat(name + " w", "Windows") * viewSize.width), + static_cast(Settings::Manager::getFloat(name + " h", "Windows") * viewSize.height)); layout->mMainWidget->setPosition(pos); layout->mMainWidget->setSize(size); @@ -1744,12 +1733,10 @@ namespace MWGui mVideoWidget->autoResize(stretch); } - WindowModal* WindowManager::getCurrentModal() const + void WindowManager::exitCurrentModal() { - if(!mCurrentModals.empty()) - return mCurrentModals.top(); - else - return NULL; + if (!mCurrentModals.empty()) + mCurrentModals.top()->exit(); } void WindowManager::removeCurrentModal(WindowModal* input) @@ -1874,4 +1861,51 @@ namespace MWGui mInventoryWindow->cycle(next); } + void WindowManager::setConsoleSelectedObject(const MWWorld::Ptr &object) + { + mConsole->setSelectedObject(object); + } + + void WindowManager::updateSpellWindow() + { + if (mSpellWindow) + mSpellWindow->updateSpells(); + } + + void WindowManager::startTravel(const MWWorld::Ptr &actor) + { + pushGuiMode(GM_Travel); + mTravelWindow->startTravel(actor); + } + + void WindowManager::startSpellBuying(const MWWorld::Ptr &actor) + { + pushGuiMode(GM_SpellBuying); + mSpellBuyingWindow->startSpellBuying(actor); + } + + void WindowManager::startTrade(const MWWorld::Ptr &actor) + { + pushGuiMode(GM_Barter); + mTradeWindow->startTrade(actor); + } + + void WindowManager::openContainer(const MWWorld::Ptr &container, bool loot) + { + pushGuiMode(GM_Container); + mContainerWindow->open(container, loot); + } + + void WindowManager::showBook(const MWWorld::Ptr &item, bool showTakeButton) + { + pushGuiMode(GM_Book); + mBookWindow->open(item, showTakeButton); + } + + void WindowManager::showScroll(const MWWorld::Ptr &item, bool showTakeButton) + { + pushGuiMode(GM_Scroll); + mScrollWindow->open(item, showTakeButton); + } + } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 735b02d2d6..297480d20f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -65,7 +65,7 @@ namespace MWGui class MainMenu; class StatsWindow; class InventoryWindow; - class JournalWindow; + struct JournalWindow; class CharacterCreation; class DragAndDrop; class ToolTips; @@ -154,17 +154,14 @@ namespace MWGui /// \todo investigate, if we really need to expose every single lousy UI element to the outside world virtual MWGui::DialogueWindow* getDialogueWindow(); - virtual MWGui::ContainerWindow* getContainerWindow(); virtual MWGui::InventoryWindow* getInventoryWindow(); - virtual MWGui::BookWindow* getBookWindow(); - virtual MWGui::ScrollWindow* getScrollWindow(); virtual MWGui::CountDialog* getCountDialog(); virtual MWGui::ConfirmationDialog* getConfirmationDialog(); virtual MWGui::TradeWindow* getTradeWindow(); - virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow(); - virtual MWGui::TravelWindow* getTravelWindow(); - virtual MWGui::SpellWindow* getSpellWindow(); - virtual MWGui::Console* getConsole(); + + virtual void updateSpellWindow(); + + virtual void setConsoleSelectedObject(const MWWorld::Ptr& object); virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount); @@ -182,8 +179,6 @@ namespace MWGui virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. - virtual void setReputation (int reputation); ///< set the current reputation value - virtual void setBounty (int bounty); ///< set the current bounty value virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty virtual void changeCell(MWWorld::CellStore* cell); ///< change the active cell @@ -277,7 +272,7 @@ namespace MWGui virtual void enableRest() { mRestAllowed = true; } virtual bool getRestEnabled(); - virtual bool getJournalAllowed() { return (mAllowed & GW_Magic); } + virtual bool getJournalAllowed() { return (mAllowed & GW_Magic) != 0; } virtual bool getPlayerSleeping(); virtual void wakeUpPlayer(); @@ -292,6 +287,12 @@ namespace MWGui virtual void startRepair(MWWorld::Ptr actor); virtual void startRepairItem(MWWorld::Ptr item); virtual void startRecharge(MWWorld::Ptr soulgem); + virtual void startTravel(const MWWorld::Ptr& actor); + virtual void startSpellBuying(const MWWorld::Ptr &actor); + virtual void startTrade(const MWWorld::Ptr &actor); + virtual void openContainer(const MWWorld::Ptr &container, bool loot); + virtual void showBook(const MWWorld::Ptr& item, bool showTakeButton); + virtual void showScroll(const MWWorld::Ptr& item, bool showTakeButton); virtual void frameStarted(float dt); @@ -317,9 +318,8 @@ namespace MWGui /// Does the current stack of GUI-windows permit saving? virtual bool isSavingAllowed() const; - /// Returns the current Modal - /** Used to send exit command to active Modal when Esc is pressed **/ - virtual WindowModal* getCurrentModal() const; + /// Send exit command to active Modal window **/ + virtual void exitCurrentModal(); /// Sets the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index fed864dfcc..88d891a028 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -11,6 +12,8 @@ #include #include +#include + #include #include "../engine.hpp" @@ -30,7 +33,7 @@ #include "../mwdialogue/dialoguemanagerimp.hpp" -#include "../mwgui/windowbase.hpp" +#include using namespace ICS; @@ -97,7 +100,8 @@ namespace MWInput { InputManager::InputManager(OEngine::Render::OgreRenderer &ogre, OMW::Engine& engine, - const std::string& userFile, bool userFileExists, bool grab) + const std::string& userFile, bool userFileExists, + const std::string& controllerBindingsFile, bool grab) : mOgre(ogre) , mPlayer(NULL) , mEngine(engine) @@ -118,8 +122,13 @@ namespace MWInput , mTimeIdle(0.f) , mOverencumberedMessageDelay(0.f) , mAlwaysRunActive(Settings::Manager::getBool("always run", "Input")) + , mSneakToggles(Settings::Manager::getBool("toggle sneak", "Input")) + , mSneaking(false) , mAttemptJump(false) , mControlsDisabled(false) + , mJoystickLastUsed(false) + , mDetectingKeyboard(false) + , mFakeDeviceID(1) { Ogre::RenderWindow* window = ogre.getWindow (); @@ -128,13 +137,14 @@ namespace MWInput mInputManager->setMouseEventCallback (this); mInputManager->setKeyboardEventCallback (this); mInputManager->setWindowEventCallback(this); + mInputManager->setControllerEventCallback(this); std::string file = userFileExists ? userFile : ""; mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last); - adjustMouseRegion (window->getWidth(), window->getHeight()); loadKeyDefaults(); + loadControllerDefaults(); for (int i = 0; i < A_Last; ++i) { @@ -148,6 +158,32 @@ namespace MWInput mControlSwitch["playermagic"] = true; mControlSwitch["playerviewswitch"] = true; mControlSwitch["vanitymode"] = true; + + /* Joystick Init */ + + //Load controller mappings +#if SDL_VERSION_ATLEAST(2,0,2) + if(controllerBindingsFile!="") + { + SDL_GameControllerAddMappingsFromFile(controllerBindingsFile.c_str()); + } +#endif + + //Open all presently connected sticks + int numSticks = SDL_NumJoysticks(); + for(int i = 0; i < numSticks; i++) + { + if(SDL_IsGameController(i)) + { + SDL_ControllerDeviceEvent evt; + evt.which = i; + controllerAdded(mFakeDeviceID, evt); + } + else + { + //ICS_LOG(std::string("Unusable controller plugged in: ")+SDL_JoystickNameForIndex(i)); + } + } } void InputManager::clear() @@ -190,10 +226,31 @@ namespace MWInput int action = channel->getNumber(); + if((previousValue == 1 || previousValue == 0) && (currentValue==1 || currentValue==0)) + { + //Is a normal button press, so don't change it at all + } + //Otherwise only trigger button presses as they go through specific points + else if(previousValue >= .8 && currentValue < .8) + { + currentValue = 0.0; + previousValue = 1.0; + } + else if(previousValue <= .6 && currentValue > .6) + { + currentValue = 1.0; + previousValue = 0.0; + } + else + { + //If it's not switching between those values, ignore the channel change. + return; + } + if (mControlSwitch["playercontrols"]) { if (action == A_Use) - mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); + mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue != 0); else if (action == A_Jump) mAttemptJump = (currentValue == 1.0 && previousValue == 0.0); } @@ -219,7 +276,6 @@ namespace MWInput break; case A_Activate: resetIdleTime(); - if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) activate(); break; @@ -298,6 +354,12 @@ namespace MWInput case A_CycleWeaponRight: MWBase::Environment::get().getWindowManager()->cycleWeapon(true); break; + case A_Sneak: + if (mSneakToggles) + { + toggleSneaking(); + } + break; } } } @@ -321,7 +383,7 @@ namespace MWInput //cursor is if( !is_relative && was_relative != is_relative ) { - mInputManager->warpMouse(mMouseX, mMouseY); + mInputManager->warpMouse(static_cast(mMouseX), static_cast(mMouseY)); } } @@ -346,6 +408,47 @@ namespace MWInput updateCursorMode(); + if(mJoystickLastUsed) + { + if (mGuiCursorEnabled) + { + float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue()*2.0f-1.0f; + float yAxis = mInputBinder->getChannel(A_MoveForwardBackward)->getValue()*2.0f-1.0f; + float zAxis = mInputBinder->getChannel(A_LookUpDown)->getValue()*2.0f-1.0f; + const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // We keep track of our own mouse position, so that moving the mouse while in + // game mode does not move the position of the GUI cursor + mMouseX += xAxis * dt * 1500.0f; + mMouseY += yAxis * dt * 1500.0f; + mMouseWheel -= static_cast(zAxis * dt * 1500.0f); + + mMouseX = std::max(0.f, std::min(mMouseX, float(viewSize.width))); + mMouseY = std::max(0.f, std::min(mMouseY, float(viewSize.height))); + + MyGUI::InputManager::getInstance().injectMouseMove(static_cast(mMouseX), static_cast(mMouseY), mMouseWheel); + mInputManager->warpMouse(static_cast(mMouseX), static_cast(mMouseY)); + } + if (mMouseLookEnabled) + { + float xAxis = mInputBinder->getChannel(A_LookLeftRight)->getValue()*2.0f-1.0f; + float yAxis = mInputBinder->getChannel(A_LookUpDown)->getValue()*2.0f-1.0f; + resetIdleTime(); + + float rot[3]; + rot[0] = yAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier; + rot[1] = 0.0f; + rot[2] = xAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f); + + // Only actually turn player when we're not in vanity mode + if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot)) + { + mPlayer->yaw(rot[2]); + mPlayer->pitch(rot[0]); + } + } + } + // Disable movement in Gui mode if (!(MWBase::Environment::get().getWindowManager()->isGuiMode() || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)) @@ -355,37 +458,80 @@ namespace MWInput if (mControlSwitch["playercontrols"]) { bool triedToMove = false; - if (actionIsActive(A_MoveLeft)) + bool isRunning = false; + if(mJoystickLastUsed) { - triedToMove = true; - mPlayer->setLeftRight (-1); + float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue(); + float yAxis = mInputBinder->getChannel(A_MoveForwardBackward)->getValue(); + if (xAxis < .5) + { + triedToMove = true; + mPlayer->setLeftRight (-1); + } + else if (xAxis > .5) + { + triedToMove = true; + mPlayer->setLeftRight (1); + } + + if (yAxis < .5) + { + triedToMove = true; + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (1); + } + else if (yAxis > .5) + { + triedToMove = true; + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (-1); + } + + else if(mPlayer->getAutoMove()) + { + triedToMove = true; + mPlayer->setForwardBackward (1); + } + isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25; + if(triedToMove) resetIdleTime(); } - else if (actionIsActive(A_MoveRight)) + else { - triedToMove = true; - mPlayer->setLeftRight (1); + if (actionIsActive(A_MoveLeft)) + { + triedToMove = true; + mPlayer->setLeftRight (-1); + } + else if (actionIsActive(A_MoveRight)) + { + triedToMove = true; + mPlayer->setLeftRight (1); + } + + if (actionIsActive(A_MoveForward)) + { + triedToMove = true; + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (1); + } + else if (actionIsActive(A_MoveBackward)) + { + triedToMove = true; + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (-1); + } + + else if(mPlayer->getAutoMove()) + { + triedToMove = true; + mPlayer->setForwardBackward (1); + } } - if (actionIsActive(A_MoveForward)) + if (!mSneakToggles) { - triedToMove = true; - mPlayer->setAutoMove (false); - mPlayer->setForwardBackward (1); + mPlayer->setSneak(actionIsActive(A_Sneak)); } - else if (actionIsActive(A_MoveBackward)) - { - triedToMove = true; - mPlayer->setAutoMove (false); - mPlayer->setForwardBackward (-1); - } - - else if(mPlayer->getAutoMove()) - { - triedToMove = true; - mPlayer->setForwardBackward (1); - } - - mPlayer->setSneak(actionIsActive(A_Sneak)); if (mAttemptJump && mControlSwitch["playerjumping"]) { @@ -394,7 +540,7 @@ namespace MWInput mOverencumberedMessageDelay = 0.f; } - if (mAlwaysRunActive) + if (mAlwaysRunActive || isRunning) mPlayer->setRunState(!actionIsActive(A_Run)); else mPlayer->setRunState(actionIsActive(A_Run)); @@ -538,6 +684,7 @@ namespace MWInput } if (!mControlsDisabled && !consumed) mInputBinder->keyPressed (arg); + mJoystickLastUsed = false; } void InputManager::textInput(const SDL_TextInputEvent &arg) @@ -550,6 +697,7 @@ namespace MWInput void InputManager::keyReleased(const SDL_KeyboardEvent &arg ) { + mJoystickLastUsed = false; OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc))); @@ -558,12 +706,13 @@ namespace MWInput void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) { + mJoystickLastUsed = false; bool guiMode = false; if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events { guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); - guiMode = MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode; + guiMode = MyGUI::InputManager::getInstance().injectMousePress(static_cast(mMouseX), static_cast(mMouseY), sdlButtonToMyGUI(id)) && guiMode; if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) { MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); @@ -582,14 +731,15 @@ namespace MWInput } void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) - { + { + mJoystickLastUsed = false; if(mInputBinder->detectingBindingState()) { mInputBinder->mouseReleased (arg, id); } else { bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); - guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)) && guiMode; + guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(static_cast(mMouseX), static_cast(mMouseY), sdlButtonToMyGUI(id)) && guiMode; if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind @@ -602,6 +752,7 @@ namespace MWInput { mInputBinder->mouseMoved (arg); + mJoystickLastUsed = false; resetIdleTime (); if (mGuiCursorEnabled) @@ -610,8 +761,8 @@ namespace MWInput // We keep track of our own mouse position, so that moving the mouse while in // game mode does not move the position of the GUI cursor - mMouseX = arg.x; - mMouseY = arg.y; + mMouseX = static_cast(arg.x); + mMouseY = static_cast(arg.y); mMouseX = std::max(0.f, std::min(mMouseX, float(viewSize.width))); mMouseY = std::max(0.f, std::min(mMouseY, float(viewSize.height))); @@ -625,8 +776,8 @@ namespace MWInput { resetIdleTime(); - double x = arg.xrel * mCameraSensitivity * (1.0f/256.f); - double y = arg.yrel * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier; + float x = arg.xrel * mCameraSensitivity * (1.0f/256.f); + float y = arg.yrel * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier; float rot[3]; rot[0] = -y; @@ -642,14 +793,87 @@ namespace MWInput if (arg.zrel && mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"]) //Check to make sure you are allowed to zoomout and there is a change { - MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel); + MWBase::Environment::get().getWorld()->changeVanityModeScale(static_cast(arg.zrel)); if (Settings::Manager::getBool("allow third person zoom", "Input")) - MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true); + MWBase::Environment::get().getWorld()->setCameraDistance(static_cast(arg.zrel), true, true); } } } + void InputManager::buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg ) + { + mJoystickLastUsed = true; + bool guiMode = false; + + if (arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_B) // We'll pretend that A is left click and B is right click + { + guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); + if(!mInputBinder->detectingBindingState()) + { + guiMode = MyGUI::InputManager::getInstance().injectMousePress(static_cast(mMouseX), static_cast(mMouseY), + sdlButtonToMyGUI((arg.button == SDL_CONTROLLER_BUTTON_B) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT)) && guiMode; + if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0) + { + MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType(false); + if (b && b->getEnabled()) + { + MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f); + } + } + } + } + + setPlayerControlsEnabled(!guiMode); + + //esc, to leave initial movie screen + OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(SDLK_ESCAPE); + bool guiFocus = MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); + setPlayerControlsEnabled(!guiFocus); + + if (!mControlsDisabled) + mInputBinder->buttonPressed(deviceID, arg); + } + + void InputManager::buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg ) + { + mJoystickLastUsed = true; + if(mInputBinder->detectingBindingState()) + mInputBinder->buttonReleased(deviceID, arg); + else if(arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_B) + { + bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); + guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(static_cast(mMouseX), static_cast(mMouseY), sdlButtonToMyGUI((arg.button == SDL_CONTROLLER_BUTTON_B) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT)) && guiMode; + + if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind + + setPlayerControlsEnabled(!guiMode); + mInputBinder->buttonReleased(deviceID, arg); + } + else + mInputBinder->buttonReleased(deviceID, arg); + + //to escape initial movie + OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(SDLK_ESCAPE); + setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc))); + } + + void InputManager::axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg ) + { + mJoystickLastUsed = true; + if (!mControlsDisabled) + mInputBinder->axisMoved(deviceID, arg); + } + + void InputManager::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg) + { + mInputBinder->controllerAdded(deviceID, arg); + } + void InputManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg) + { + mInputBinder->controllerRemoved(arg); + } + void InputManager::windowFocusChange(bool have_focus) { } @@ -672,7 +896,7 @@ namespace MWInput void InputManager::toggleMainMenu() { if (MyGUI::InputManager::getInstance().isModalAny()) { - MWBase::Environment::get().getWindowManager()->getCurrentModal()->exit(); + MWBase::Environment::get().getWindowManager()->exitCurrentModal(); return; } @@ -846,7 +1070,7 @@ namespace MWInput } else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu) { while(MyGUI::InputManager::getInstance().isModalAny()) { //Handle any open Modal windows - MWBase::Environment::get().getWindowManager()->getCurrentModal()->exit(); + MWBase::Environment::get().getWindowManager()->exitCurrentModal(); } MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); //And handle the actual main window } @@ -874,6 +1098,13 @@ namespace MWInput Settings::Manager::setBool("always run", "Input", mAlwaysRunActive); } + void InputManager::toggleSneaking() + { + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; + mSneaking = !mSneaking; + mPlayer->setSneak(mSneaking); + } + void InputManager::resetIdleTime() { if (mTimeIdle < 0) @@ -895,7 +1126,7 @@ namespace MWInput bool InputManager::actionIsActive (int id) { - return mInputBinder->getChannel (id)->getValue () == 1; + return (mInputBinder->getChannel (id)->getValue ()==1.0); } void InputManager::loadKeyDefaults (bool force) @@ -968,14 +1199,88 @@ namespace MWInput && mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS )) { - clearAllBindings (control); + clearAllKeyBindings(control); if (defaultKeyBindings.find(i) != defaultKeyBindings.end() && !mInputBinder->isKeyBound(defaultKeyBindings[i])) + { + control->setInitialValue(0.0f); mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE); + } else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end() && !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i])) + { + control->setInitialValue(0.0f); mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); + } + } + } + } + + void InputManager::loadControllerDefaults(bool force) + { + // using hardcoded key defaults is inevitable, if we want the configuration files to stay valid + // across different versions of OpenMW (in the case where another input action is added) + std::map defaultButtonBindings; + + defaultButtonBindings[A_Activate] = SDL_CONTROLLER_BUTTON_A; + defaultButtonBindings[A_ToggleWeapon] = SDL_CONTROLLER_BUTTON_X; + defaultButtonBindings[A_ToggleSpell] = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; + //defaultButtonBindings[A_QuickButtonsMenu] = SDL_GetButtonFromScancode(SDL_SCANCODE_F1); // Need to implement, should be ToggleSpell(5) AND Wait(9) + defaultButtonBindings[A_Sneak] = SDL_CONTROLLER_BUTTON_RIGHTSTICK; + defaultButtonBindings[A_Jump] = SDL_CONTROLLER_BUTTON_Y; + defaultButtonBindings[A_Journal] = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; + defaultButtonBindings[A_Rest] = SDL_CONTROLLER_BUTTON_BACK; + defaultButtonBindings[A_TogglePOV] = SDL_CONTROLLER_BUTTON_LEFTSTICK; + defaultButtonBindings[A_Inventory] = SDL_CONTROLLER_BUTTON_B; + defaultButtonBindings[A_GameMenu] = SDL_CONTROLLER_BUTTON_START; + defaultButtonBindings[A_QuickSave] = SDL_CONTROLLER_BUTTON_GUIDE; + defaultButtonBindings[A_QuickKey1] = SDL_CONTROLLER_BUTTON_DPAD_UP; + defaultButtonBindings[A_QuickKey2] = SDL_CONTROLLER_BUTTON_DPAD_LEFT; + defaultButtonBindings[A_QuickKey3] = SDL_CONTROLLER_BUTTON_DPAD_DOWN; + defaultButtonBindings[A_QuickKey4] = SDL_CONTROLLER_BUTTON_DPAD_RIGHT; + + std::map defaultAxisBindings; + defaultAxisBindings[A_MoveForwardBackward] = SDL_CONTROLLER_AXIS_LEFTY; + defaultAxisBindings[A_MoveLeftRight] = SDL_CONTROLLER_AXIS_LEFTX; + defaultAxisBindings[A_LookUpDown] = SDL_CONTROLLER_AXIS_RIGHTY; + defaultAxisBindings[A_LookLeftRight] = SDL_CONTROLLER_AXIS_RIGHTX; + defaultAxisBindings[A_Use] = SDL_CONTROLLER_AXIS_TRIGGERRIGHT; + + for (int i = 0; i < A_Last; i++) + { + ICS::Control* control; + bool controlExists = mInputBinder->getChannel(i)->getControlsCount () != 0; + if (!controlExists) + { + float initial; + if (defaultButtonBindings.find(i) != defaultButtonBindings.end()) + initial = 0.0f; + else initial = 0.5f; + control = new ICS::Control(boost::lexical_cast(i), false, true, initial, ICS::ICS_MAX, ICS::ICS_MAX); + mInputBinder->addControl(control); + control->attachChannel(mInputBinder->getChannel(i), ICS::Channel::DIRECT); + } + else + { + control = mInputBinder->getChannel(i)->getAttachedControls ().front().control; + } + + if (!controlExists || force || ( mInputBinder->getJoystickAxisBinding (control, mFakeDeviceID, ICS::Control::INCREASE) == ICS::InputControlSystem::UNASSIGNED && mInputBinder->getJoystickButtonBinding (control, mFakeDeviceID, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS )) + { + clearAllControllerBindings(control); + + if (defaultButtonBindings.find(i) != defaultButtonBindings.end()) + { + control->setInitialValue(0.0f); + mInputBinder->addJoystickButtonBinding(control, mFakeDeviceID, defaultButtonBindings[i], ICS::Control::INCREASE); + } + else if (defaultAxisBindings.find(i) != defaultAxisBindings.end()) + { + control->setValue(0.5f); + control->setInitialValue(0.5f); + mInputBinder->addJoystickAxisBinding(control, mFakeDeviceID, defaultAxisBindings[i], ICS::Control::INCREASE); + } } } } @@ -1029,7 +1334,7 @@ namespace MWInput return "#{" + descriptions[action] + "}"; } - std::string InputManager::getActionBindingName (int action) + std::string InputManager::getActionKeyBindingName (int action) { if (mInputBinder->getChannel (action)->getControlsCount () == 0) return "#{sNone}"; @@ -1044,7 +1349,81 @@ namespace MWInput return "#{sNone}"; } - std::vector InputManager::getActionSorting() + std::string InputManager::getActionControllerBindingName (int action) + { + if (mInputBinder->getChannel (action)->getControlsCount () == 0) + return "#{sNone}"; + + ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; + + if (mInputBinder->getJoystickAxisBinding (c, mFakeDeviceID, ICS::Control::INCREASE) != ICS::InputControlSystem::UNASSIGNED) + return sdlControllerAxisToString(mInputBinder->getJoystickAxisBinding (c, mFakeDeviceID, ICS::Control::INCREASE)); + else if (mInputBinder->getJoystickButtonBinding (c, mFakeDeviceID, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS ) + return sdlControllerButtonToString(mInputBinder->getJoystickButtonBinding (c, mFakeDeviceID, ICS::Control::INCREASE)); + else + return "#{sNone}"; + } + + std::string InputManager::sdlControllerButtonToString(int button) + { + switch(button) + { + case SDL_CONTROLLER_BUTTON_A: + return "A Button"; + case SDL_CONTROLLER_BUTTON_B: + return "B Button"; + case SDL_CONTROLLER_BUTTON_BACK: + return "Back Button"; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + return "DPad Down"; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + return "DPad Left"; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + return "DPad Right"; + case SDL_CONTROLLER_BUTTON_DPAD_UP: + return "DPad Up"; + case SDL_CONTROLLER_BUTTON_GUIDE: + return "Guide Button"; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: + return "Left Shoulder"; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: + return "Left Stick Button"; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: + return "Right Shoulder"; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: + return "Right Stick Button"; + case SDL_CONTROLLER_BUTTON_START: + return "Start Button"; + case SDL_CONTROLLER_BUTTON_X: + return "X Button"; + case SDL_CONTROLLER_BUTTON_Y: + return "Y Button"; + default: + return "Button " + boost::lexical_cast(button); + } + } + std::string InputManager::sdlControllerAxisToString(int axis) + { + switch(axis) + { + case SDL_CONTROLLER_AXIS_LEFTX: + return "Left Stick X"; + case SDL_CONTROLLER_AXIS_LEFTY: + return "Left Stick Y"; + case SDL_CONTROLLER_AXIS_RIGHTX: + return "Right Stick X"; + case SDL_CONTROLLER_AXIS_RIGHTY: + return "Right Stick Y"; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: + return "Left Trigger"; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + return "Right Trigger"; + default: + return "Axis " + boost::lexical_cast(axis); + } + } + + std::vector InputManager::getActionKeySorting() { std::vector ret; ret.push_back(A_MoveForward); @@ -1086,11 +1465,42 @@ namespace MWInput return ret; } - - void InputManager::enableDetectingBindingMode (int action) + std::vector InputManager::getActionControllerSorting() { - ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; + std::vector ret; + ret.push_back(A_TogglePOV); + ret.push_back(A_Sneak); + ret.push_back(A_Activate); + ret.push_back(A_Use); + ret.push_back(A_ToggleWeapon); + ret.push_back(A_ToggleSpell); + ret.push_back(A_AutoMove); + ret.push_back(A_Jump); + ret.push_back(A_Inventory); + ret.push_back(A_Journal); + ret.push_back(A_Rest); + ret.push_back(A_QuickSave); + ret.push_back(A_QuickLoad); + ret.push_back(A_Screenshot); + ret.push_back(A_QuickKeysMenu); + ret.push_back(A_QuickKey1); + ret.push_back(A_QuickKey2); + ret.push_back(A_QuickKey3); + ret.push_back(A_QuickKey4); + ret.push_back(A_QuickKey5); + ret.push_back(A_QuickKey6); + ret.push_back(A_QuickKey7); + ret.push_back(A_QuickKey8); + ret.push_back(A_QuickKey9); + ret.push_back(A_QuickKey10); + return ret; + } + + void InputManager::enableDetectingBindingMode (int action, bool keyboard) + { + mDetectingKeyboard = keyboard; + ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; mInputBinder->enableDetectingBindingState (c, ICS::Control::INCREASE); } @@ -1106,9 +1516,17 @@ namespace MWInput { //Disallow binding escape key if(key==SDL_SCANCODE_ESCAPE) + { + //Stop binding if esc pressed + mInputBinder->cancelDetectingBindingState(); + MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); + return; + } + if(!mDetectingKeyboard) return; - clearAllBindings(control); + clearAllKeyBindings(control); + control->setInitialValue(0.0f); ICS::DetectingBindingListener::keyBindingDetected (ICS, control, key, direction); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } @@ -1116,59 +1534,69 @@ namespace MWInput void InputManager::mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , unsigned int button, ICS::Control::ControlChangingDirection direction) { - clearAllBindings(control); + if(!mDetectingKeyboard) + return; + clearAllKeyBindings(control); + control->setInitialValue(0.0f); ICS::DetectingBindingListener::mouseButtonBindingDetected (ICS, control, button, direction); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } - void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int axis, ICS::Control::ControlChangingDirection direction) + void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , int axis, ICS::Control::ControlChangingDirection direction) { - clearAllBindings(control); - ICS::DetectingBindingListener::joystickAxisBindingDetected (ICS, control, deviceId, axis, direction); + //only allow binding to the trigers + if(axis != SDL_CONTROLLER_AXIS_TRIGGERLEFT && axis != SDL_CONTROLLER_AXIS_TRIGGERRIGHT) + return; + if(mDetectingKeyboard) + return; + + clearAllControllerBindings(control); + control->setValue(0.5f); //axis bindings must start at 0.5 + control->setInitialValue(0.5f); + ICS::DetectingBindingListener::joystickAxisBindingDetected (ICS, deviceID, control, axis, direction); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } - void InputManager::joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction) + void InputManager::joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction) { - clearAllBindings(control); - ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, control, deviceId, button, direction); + if(mDetectingKeyboard) + return; + clearAllControllerBindings(control); + control->setInitialValue(0.0f); + ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, deviceID, control, button, direction); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); } - void InputManager::joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction) - { - clearAllBindings(control); - ICS::DetectingBindingListener::joystickPOVBindingDetected (ICS, control, deviceId, pov, axis, direction); - MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); - } - - void InputManager::joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int slider, ICS::Control::ControlChangingDirection direction) - { - clearAllBindings(control); - ICS::DetectingBindingListener::joystickSliderBindingDetected (ICS, control, deviceId, slider, direction); - MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); - } - - void InputManager::clearAllBindings (ICS::Control* control) + void InputManager::clearAllKeyBindings (ICS::Control* control) { // right now we don't really need multiple bindings for the same action, so remove all others first if (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN) mInputBinder->removeKeyBinding (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE)); if (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) mInputBinder->removeMouseButtonBinding (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE)); - - /// \todo add joysticks here once they are added } - void InputManager::resetToDefaultBindings() + void InputManager::clearAllControllerBindings (ICS::Control* control) + { + // right now we don't really need multiple bindings for the same action, so remove all others first + if (mInputBinder->getJoystickAxisBinding (control, mFakeDeviceID, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN) + mInputBinder->removeJoystickAxisBinding (mFakeDeviceID, mInputBinder->getJoystickAxisBinding (control, mFakeDeviceID, ICS::Control::INCREASE)); + if (mInputBinder->getJoystickButtonBinding (control, mFakeDeviceID, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) + mInputBinder->removeJoystickButtonBinding (mFakeDeviceID, mInputBinder->getJoystickButtonBinding (control, mFakeDeviceID, ICS::Control::INCREASE)); + } + + void InputManager::resetToDefaultKeyBindings() { loadKeyDefaults(true); } + void InputManager::resetToDefaultControllerBindings() + { + loadControllerDefaults(true); + } + MyGUI::MouseButton InputManager::sdlButtonToMyGUI(Uint8 button) { //The right button is the second button, according to MyGUI diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 851f249715..5588010236 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -4,6 +4,7 @@ #include "../mwgui/mode.hpp" #include +#include #include "../mwbase/inputmanager.hpp" #include @@ -38,7 +39,12 @@ namespace ICS namespace MyGUI { - class MouseButton; + struct MouseButton; +} + +namespace Files +{ + struct ConfigurationManager; } #include @@ -55,13 +61,15 @@ namespace MWInput public SFO::KeyListener, public SFO::MouseListener, public SFO::WindowListener, + public SFO::ControllerListener, public ICS::ChannelListener, public ICS::DetectingBindingListener { public: InputManager(OEngine::Render::OgreRenderer &_ogre, OMW::Engine& engine, - const std::string& userFile, bool userFileExists, bool grab); + const std::string& userFile, bool userFileExists, + const std::string& controllerBindingsFile, bool grab); virtual ~InputManager(); @@ -82,11 +90,16 @@ namespace MWInput virtual bool getControlSwitch (const std::string& sw); virtual std::string getActionDescription (int action); - virtual std::string getActionBindingName (int action); + virtual std::string getActionKeyBindingName (int action); + virtual std::string getActionControllerBindingName (int action); virtual int getNumActions() { return A_Last; } - virtual std::vector getActionSorting (); - virtual void enableDetectingBindingMode (int action); - virtual void resetToDefaultBindings(); + virtual std::vector getActionKeySorting(); + virtual std::vector getActionControllerSorting(); + virtual void enableDetectingBindingMode (int action, bool keyboard); + virtual void resetToDefaultKeyBindings(); + virtual void resetToDefaultControllerBindings(); + + virtual bool joystickLastUsed() {return mJoystickLastUsed;} public: virtual void keyPressed(const SDL_KeyboardEvent &arg ); @@ -97,6 +110,12 @@ namespace MWInput virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual void mouseMoved( const SFO::MouseMotionEvent &arg ); + virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg); + virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg); + virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg); + virtual void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg); + virtual void controllerRemoved(const SDL_ControllerDeviceEvent &arg); + virtual void windowVisibilityChange( bool visible ); virtual void windowFocusChange( bool have_focus ); virtual void windowResized (int x, int y); @@ -113,21 +132,17 @@ namespace MWInput virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control , unsigned int button, ICS::Control::ControlChangingDirection direction); - virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int axis, ICS::Control::ControlChangingDirection direction); + virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , int axis, ICS::Control::ControlChangingDirection direction); - virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction); + virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction); - virtual void joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction); - - virtual void joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , int deviceId, int slider, ICS::Control::ControlChangingDirection direction); - - void clearAllBindings (ICS::Control* control); + void clearAllKeyBindings (ICS::Control* control); + void clearAllControllerBindings (ICS::Control* control); private: + bool mJoystickLastUsed; OEngine::Render::OgreRenderer &mOgre; MWWorld::Player* mPlayer; OMW::Engine& mEngine; @@ -156,6 +171,8 @@ namespace MWInput bool mMouseLookEnabled; bool mGuiCursorEnabled; + bool mDetectingKeyboard; + float mOverencumberedMessageDelay; float mMouseX; @@ -163,6 +180,8 @@ namespace MWInput int mMouseWheel; bool mUserFileExists; bool mAlwaysRunActive; + bool mSneakToggles; + bool mSneaking; bool mAttemptJump; std::map mControlSwitch; @@ -171,6 +190,9 @@ namespace MWInput void adjustMouseRegion(int width, int height); MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button); + virtual std::string sdlControllerAxisToString(int axis); + virtual std::string sdlControllerButtonToString(int button); + void resetIdleTime(); void updateIdleTime(float dt); @@ -188,6 +210,7 @@ namespace MWInput void toggleJournal(); void activate(); void toggleWalking(); + void toggleSneaking(); void toggleAutoMove(); void rest(); void quickLoad(); @@ -199,6 +222,9 @@ namespace MWInput bool actionIsActive (int id); void loadKeyDefaults(bool force = false); + void loadControllerDefaults(bool force = false); + + int mFakeDeviceID; //As we only support one controller at a time, use a fake deviceID so we don't lose bindings when switching controllers private: enum Actions @@ -263,6 +289,11 @@ namespace MWInput A_ToggleDebug, + A_LookUpDown, //Joystick look + A_LookLeftRight, + A_MoveForwardBackward, + A_MoveLeftRight, + A_Last // Marker for the last item }; }; diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 6e15449e19..a6cc9af8ef 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -1,5 +1,7 @@ #include "activespells.hpp" +#include + #include #include @@ -74,9 +76,9 @@ namespace MWMechanics for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) { - int duration = effectIt->mDuration; + double duration = effectIt->mDuration; MWWorld::TimeStamp end = start; - end += static_cast (duration)* + end += duration * MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); if (end>now) @@ -110,7 +112,7 @@ namespace MWMechanics { const std::vector& effects = iterator->second.mEffects; - int duration = 0; + float duration = 0; for (std::vector::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter) @@ -152,12 +154,7 @@ namespace MWMechanics void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, const std::string &displayName, int casterActorId) { - bool exists = false; - for (TContainer::const_iterator it = begin(); it != end(); ++it) - { - if (id == it->first) - exists = true; - } + TContainer::iterator it(mSpells.find(id)); ActiveSpellParams params; params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp(); @@ -165,14 +162,44 @@ namespace MWMechanics params.mDisplayName = displayName; params.mCasterActorId = casterActorId; - if (!exists || stack) - mSpells.insert (std::make_pair(id, params)); + if (it == end() || stack) + { + mSpells.insert(std::make_pair(id, params)); + } else - mSpells.find(id)->second = params; + { + // addSpell() is called with effects for a range. + // but a spell may have effects with different ranges (e.g. Touch & Target) + // so, if we see new effects for same spell assume additional + // spell effects and add to existing effects of spell + mergeEffects(params.mEffects, it->second.mEffects); + it->second = params; + } mSpellsChanged = true; } + void ActiveSpells::mergeEffects(std::vector& addTo, const std::vector& from) + { + for (std::vector::const_iterator effect(from.begin()); effect != from.end(); ++effect) + { + // if effect is not in addTo, add it + bool missing = true; + for (std::vector::const_iterator iter(addTo.begin()); iter != addTo.end(); ++iter) + { + if ((effect->mEffectId == iter->mEffectId) && (effect->mArg == iter->mArg)) + { + missing = false; + break; + } + } + if (missing) + { + addTo.push_back(*effect); + } + } + } + void ActiveSpells::removeEffects(const std::string &id) { mSpells.erase(Misc::StringUtils::lowerCase(id)); @@ -191,7 +218,7 @@ namespace MWMechanics std::string name = it->second.mDisplayName; float remainingTime = effectIt->mDuration + - (it->second.mTimeStamp - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale; + static_cast(it->second.mTimeStamp - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale; float magnitude = effectIt->mMagnitude; if (magnitude) @@ -204,8 +231,7 @@ namespace MWMechanics { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ) { - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (roll < chance) + if (OEngine::Misc::Rng::roll0to99() < chance) mSpells.erase(it++); else ++it; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 4f9d15d8c1..2a4d75d402 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -55,6 +55,9 @@ namespace MWMechanics void rebuildEffects() const; + /// Add any effects that are in "from" and not in "addTo" to "addTo" + void mergeEffects(std::vector& addTo, const std::vector& from); + double timeToExpire (const TIterator& iterator) const; ///< Returns time (in in-game hours) until the spell pointed to by \a iterator /// expires. diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index f8068e8000..c6df241546 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -54,9 +54,17 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a { if (actor.getClass().getContainerStore(actor).count(item) == 0) { - MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor); + MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor); + MWWorld::Ptr newPtr = *store.MWWorld::ContainerStore::add(item, 1, actor); MWWorld::ActionEquip action(newPtr); action.execute(actor); + MWWorld::ContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + // change draw state only if the item is in player's right hand + if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr() + && rightHand != store.end() && newPtr == *rightHand) + { + MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Weapon); + } } } else @@ -84,14 +92,14 @@ bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate) // FIXME: charge should be a float, not int so that damage < 1 per frame can be applied. // This was also a bug in the original engine. charge -= - std::min(disintegrate, - static_cast(charge)); + std::min(static_cast(disintegrate), + charge); item->getCellRef().setCharge(charge); if (charge == 0) { // Will unequip the broken item and try to find a replacement - if (ptr.getRefData().getHandle() != "player") + if (ptr != MWBase::Environment::get().getWorld()->getPlayerPtr()) inv.autoEquip(ptr); else inv.unequipItem(*item, ptr); @@ -146,6 +154,7 @@ void adjustCommandedActor (const MWWorld::Ptr& actor) if (check.mCommanded && !hasCommandPackage) { + // FIXME: don't use refid string MWMechanics::AiFollow package("player", true); stats.getAiSequence().stack(package, actor); } @@ -163,7 +172,7 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0; int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); - health = 0.1 * endurance; + health = 0.1f * endurance; magicka = 0; if (!stunted) @@ -203,7 +212,7 @@ namespace MWMechanics static const float fSoulgemMult = world->getStore().get().find("fSoulgemMult")->getFloat(); - float creatureSoulValue = mCreature.get()->mBase->mData.mSoul; + int creatureSoulValue = mCreature.get()->mBase->mData.mSoul; if (creatureSoulValue == 0) return; @@ -236,7 +245,7 @@ namespace MWMechanics gem->getContainerStore()->unstack(*gem, caster); gem->getCellRef().setSoul(mCreature.getCellRef().getRefId()); - if (caster.getRefData().getHandle() == "player") + if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sSoultrapSuccess}"); const ESM::Static* fx = MWBase::Environment::get().getWorld()->getStore().get() @@ -425,7 +434,7 @@ namespace MWMechanics int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getModified(); float base = 1.f; - if (ptr.getCellRef().getRefId() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) base = MWBase::Environment::get().getWorld()->getStore().get().find("fPCbaseMagickaMult")->getFloat(); else base = MWBase::Environment::get().getWorld()->getStore().get().find("fNPCbaseMagickaMult")->getFloat(); @@ -515,12 +524,12 @@ namespace MWMechanics for(int i = 0;i < ESM::Attribute::Length;++i) { AttributeValue stat = creatureStats.getAttribute(i); - stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).getMagnitude() - + stat.setModifier(static_cast(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).getMagnitude() - effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude()); + effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude())); - stat.damage(effects.get(EffectKey(ESM::MagicEffect::DamageAttribute, i)).getMagnitude() * duration * 1.5); - stat.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreAttribute, i)).getMagnitude() * duration * 1.5); + stat.damage(effects.get(EffectKey(ESM::MagicEffect::DamageAttribute, i)).getMagnitude() * duration); + stat.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreAttribute, i)).getMagnitude() * duration); creatureStats.setAttribute(i, stat); } @@ -535,7 +544,7 @@ namespace MWMechanics { spells.worsenCorprus(it->first); - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}"); } } @@ -547,7 +556,9 @@ namespace MWMechanics { DynamicStat stat = creatureStats.getDynamic(i); stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).getMagnitude() - - effects.get(ESM::MagicEffect::DrainHealth+i).getMagnitude()); + effects.get(ESM::MagicEffect::DrainHealth+i).getMagnitude(), + // Fatigue can be decreased below zero meaning the actor will be knocked out + i == 2); float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).getMagnitude() @@ -566,19 +577,19 @@ namespace MWMechanics if (!creature || ptr.get()->mBase->mData.mType == ESM::Creature::Creatures) { Stat stat = creatureStats.getAiSetting(CreatureStats::AI_Fight); - stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid+creature).getMagnitude() - - creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).getMagnitude()); + stat.setModifier(static_cast(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid + creature).getMagnitude() + - creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).getMagnitude())); creatureStats.setAiSetting(CreatureStats::AI_Fight, stat); stat = creatureStats.getAiSetting(CreatureStats::AI_Flee); - stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid+creature).getMagnitude() - - creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).getMagnitude()); + stat.setModifier(static_cast(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid + creature).getMagnitude() + - creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).getMagnitude())); creatureStats.setAiSetting(CreatureStats::AI_Flee, stat); } if (creature && ptr.get()->mBase->mData.mType == ESM::Creature::Undead) { Stat stat = creatureStats.getAiSetting(CreatureStats::AI_Flee); - stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).getMagnitude()); + stat.setModifier(static_cast(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).getMagnitude())); creatureStats.setAiSetting(CreatureStats::AI_Flee, stat); } @@ -655,7 +666,7 @@ namespace MWMechanics } } - if (receivedMagicDamage && ptr.getRefData().getHandle() == "player") + if (receivedMagicDamage && ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); creatureStats.setHealth(health); @@ -741,7 +752,7 @@ namespace MWMechanics for (std::map::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it) { bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end(); - int magnitude = creatureStats.getMagicEffects().get(it->first).getMagnitude(); + float magnitude = creatureStats.getMagicEffects().get(it->first).getMagnitude(); if (found != (magnitude > 0)) { std::string itemGmst = it->second; @@ -782,12 +793,12 @@ namespace MWMechanics for(int i = 0;i < ESM::Skill::Length;++i) { SkillValue& skill = npcStats.getSkill(i); - skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude() - + skill.setModifier(static_cast(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude() - effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude()); + effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude())); - skill.damage(effects.get(EffectKey(ESM::MagicEffect::DamageSkill, i)).getMagnitude() * duration * 1.5); - skill.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreSkill, i)).getMagnitude() * duration * 1.5); + skill.damage(effects.get(EffectKey(ESM::MagicEffect::DamageSkill, i)).getMagnitude() * duration); + skill.restore(effects.get(EffectKey(ESM::MagicEffect::RestoreSkill, i)).getMagnitude() * duration); } } @@ -838,7 +849,7 @@ namespace MWMechanics void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) { - bool isPlayer = ptr.getRefData().getHandle()=="player"; + bool isPlayer = (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()); MWWorld::InventoryStore &inventoryStore = ptr.getClass().getInventoryStore(ptr); MWWorld::ContainerStoreIterator heldIter = @@ -1147,7 +1158,7 @@ namespace MWMechanics // Handle player last, in case a cell transition occurs by casting a teleportation spell // (would invalidate the iterator) - if (iter->first.getCellRef().getRefId() == "player") + if (iter->first == MWBase::Environment::get().getWorld()->getPlayerPtr()) { playerCharacter = iter->second->getCharacterController(); continue; @@ -1331,7 +1342,7 @@ namespace MWMechanics ? (stats.getMagicka().getModified() - stats.getMagicka().getCurrent()) / magickaPerHour : 1.0f; - int autoHours = std::ceil(std::max(1.f, std::max(healthHours, magickaHours))); + int autoHours = static_cast(std::ceil(std::max(1.f, std::max(healthHours, magickaHours)))); return autoHours; } diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index b9954337d5..a73d955c56 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -31,12 +31,12 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, AiState& stat float x = pos.pos[0] - mLastPos.pos[0]; float y = pos.pos[1] - mLastPos.pos[1]; float z = pos.pos[2] - mLastPos.pos[2]; - int distance = x * x + y * y + z * z; + float distance = x * x + y * y + z * z; if(distance < 10 * 10) { //Got stuck, didn't move if(mAdjAngle == 0) //Try going in various directions mAdjAngle = 1.57079632679f; //pi/2 else if (mAdjAngle == 1.57079632679f) - mAdjAngle = -1.57079632679; + mAdjAngle = -1.57079632679f; else mAdjAngle = 0; mDuration = 1; //reset timer diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index fd4fd293d6..2f68087e58 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -2,6 +2,8 @@ #include +#include + #include #include "../mwworld/class.hpp" @@ -393,7 +395,7 @@ namespace MWMechanics if (!distantCombat) attackType = chooseBestAttack(weapon, movement); else attackType = ESM::Weapon::AT_Chop; // cause it's =0 - strength = static_cast(rand()) / RAND_MAX; + strength = OEngine::Misc::Rng::rollClosedProbability(); // Note: may be 0 for some animations timerAttack = minMaxAttackDuration[attackType][0] + @@ -404,8 +406,7 @@ namespace MWMechanics { const MWWorld::ESMStore &store = world->getStore(); int chance = store.get().find("iVoiceAttackOdds")->getInt(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (roll < chance) + if (OEngine::Misc::Rng::roll0to99() < chance) { MWBase::Environment::get().getDialogueManager()->say(actor, "attack"); } @@ -512,17 +513,17 @@ namespace MWMechanics { if(movement.mPosition[0] || movement.mPosition[1]) { - timerCombatMove = 0.1f + 0.1f * static_cast(rand())/RAND_MAX; + timerCombatMove = 0.1f + 0.1f * OEngine::Misc::Rng::rollClosedProbability(); combatMove = true; } // only NPCs are smart enough to use dodge movements else if(actorClass.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeAttack/2))) { //apply sideway movement (kind of dodging) with some probability - if(static_cast(rand())/RAND_MAX < 0.25) + if (OEngine::Misc::Rng::rollClosedProbability() < 0.25) { - movement.mPosition[0] = static_cast(rand())/RAND_MAX < 0.5? 1: -1; - timerCombatMove = 0.05f + 0.15f * static_cast(rand())/RAND_MAX; + movement.mPosition[0] = OEngine::Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; + timerCombatMove = 0.05f + 0.15f * OEngine::Misc::Rng::rollClosedProbability(); combatMove = true; } } @@ -580,7 +581,7 @@ namespace MWMechanics buildNewPath(actor, target); //may fail to build a path, check before use //delete visited path node - mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); + mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1]); // This works on the borders between the path grid and areas with no waypoints. if(inLOS && mPathFinder.getPath().size() > 1) @@ -588,7 +589,7 @@ namespace MWMechanics // get point just before target std::list::const_iterator pntIter = --mPathFinder.getPath().end(); --pntIter; - Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ); + Ogre::Vector3 vBeforeTarget(PathFinder::MakeOgreVector3(*pntIter)); // if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target if(distToTarget <= (vTargetPos - vBeforeTarget).length()) @@ -637,7 +638,7 @@ namespace MWMechanics float s2 = speed2 * t; float t_swing = minMaxAttackDuration[ESM::Weapon::AT_Thrust][0] + - (minMaxAttackDuration[ESM::Weapon::AT_Thrust][1] - minMaxAttackDuration[ESM::Weapon::AT_Thrust][0]) * static_cast(rand()) / RAND_MAX; + (minMaxAttackDuration[ESM::Weapon::AT_Thrust][1] - minMaxAttackDuration[ESM::Weapon::AT_Thrust][0]) * OEngine::Misc::Rng::rollClosedProbability(); if (t + s2/speed1 <= t_swing) { @@ -685,27 +686,21 @@ namespace MWMechanics if(!mPathFinder.getPath().empty()) { ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ); + Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(lastPt)); dist = (newPathTarget - currPathTarget).length(); } else dist = 1e+38F; // necessarily construct a new path - float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300 : 100; + float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300.0f : 100.0f; //construct new path only if target has moved away more than on [targetPosThreshold] if(dist > targetPosThreshold) { ESM::Position pos = actor.getRefData().getPosition(); - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); - ESM::Pathgrid::Point dest; - dest.mX = newPathTarget.x; - dest.mY = newPathTarget.y; - dest.mZ = newPathTarget.z; + ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(newPathTarget)); if(!mPathFinder.isPathConstructed()) mPathFinder.buildPath(start, dest, actor.getCell(), false); @@ -767,10 +762,10 @@ ESM::Weapon::AttackType chooseBestAttack(const ESM::Weapon* weapon, MWMechanics: if (weapon == NULL) { //hand-to-hand deal equal damage for each type - float roll = static_cast(rand())/RAND_MAX; + float roll = OEngine::Misc::Rng::rollClosedProbability(); if(roll <= 0.333f) //side punch { - movement.mPosition[0] = (static_cast(rand())/RAND_MAX < 0.5f)? 1: -1; + movement.mPosition[0] = OEngine::Misc::Rng::rollClosedProbability() ? 1.0f : -1.0f; movement.mPosition[1] = 0; attackType = ESM::Weapon::AT_Slash; } @@ -792,16 +787,16 @@ ESM::Weapon::AttackType chooseBestAttack(const ESM::Weapon* weapon, MWMechanics: int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1])/2; int thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1])/2; - float total = slash + chop + thrust; + float total = static_cast(slash + chop + thrust); - float roll = static_cast(rand())/RAND_MAX; - if(roll <= static_cast(slash)/total) + float roll = OEngine::Misc::Rng::rollClosedProbability(); + if(roll <= (slash/total)) { - movement.mPosition[0] = (static_cast(rand())/RAND_MAX < 0.5f)? 1: -1; + movement.mPosition[0] = (OEngine::Misc::Rng::rollClosedProbability() < 0.5f) ? 1.0f : -1.0f; movement.mPosition[1] = 0; attackType = ESM::Weapon::AT_Slash; } - else if(roll <= (static_cast(slash) + static_cast(thrust))/total) + else if(roll <= (slash + (thrust/total))) { movement.mPosition[1] = 1; attackType = ESM::Weapon::AT_Thrust; diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 175b980011..33e3c3d679 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -323,14 +323,14 @@ namespace MWMechanics if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length) { const float attributePriorities[ESM::Attribute::Length] = { - 1.f, // Strength - 0.5, // Intelligence - 0.6, // Willpower - 0.7, // Agility - 0.5, // Speed - 0.8, // Endurance - 0.7, // Personality - 0.3 // Luck + 1.0f, // Strength + 0.5f, // Intelligence + 0.6f, // Willpower + 0.7f, // Agility + 0.5f, // Speed + 0.8f, // Endurance + 0.7f, // Personality + 0.3f // Luck }; rating *= attributePriorities[effect.mAttribute]; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index c89cfe4923..91bf7c9b03 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -23,7 +23,7 @@ namespace MWMechanics { AiEscort::AiEscort(const std::string &actorId, int duration, float x, float y, float z) - : mActorId(actorId), mX(x), mY(y), mZ(z), mRemainingDuration(duration) + : mActorId(actorId), mX(x), mY(y), mZ(z), mRemainingDuration(static_cast(duration)) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -36,7 +36,7 @@ namespace MWMechanics } AiEscort::AiEscort(const std::string &actorId, const std::string &cellId,int duration, float x, float y, float z) - : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mRemainingDuration(duration) + : mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mRemainingDuration(static_cast(duration)) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { @@ -86,13 +86,13 @@ namespace MWMechanics for (short counter = 0; counter < 3; counter++) differenceBetween[counter] = (leaderPos[counter] - followerPos[counter]); - float distanceBetweenResult = + double distanceBetweenResult = (differenceBetween[0] * differenceBetween[0]) + (differenceBetween[1] * differenceBetween[1]) + (differenceBetween[2] * differenceBetween[2]); if(distanceBetweenResult <= mMaxDist * mMaxDist) { - ESM::Pathgrid::Point point(mX,mY,mZ); + ESM::Pathgrid::Point point(static_cast(mX), static_cast(mY), static_cast(mZ)); point.mAutogenerated = 0; point.mConnectionNum = 0; point.mUnknown = 0; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index f015bb8a4e..52a975320d 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -16,7 +16,7 @@ MWMechanics::AiPackage::~AiPackage() {} -MWMechanics::AiPackage::AiPackage() : mTimer(.26), mStuckTimer(0) { //mTimer starts at .26 to force initial pathbuild +MWMechanics::AiPackage::AiPackage() : mTimer(0.26f), mStuckTimer(0) { //mTimer starts at .26 to force initial pathbuild } @@ -86,7 +86,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //************************ /// Checks if you aren't moving; attempts to unstick you //************************ - if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished? + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1])) //Path finished? return true; else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something { diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 80b48fc378..179ae440bb 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -16,7 +16,7 @@ namespace ESM { namespace AiSequence { - class AiSequence; + struct AiSequence; } } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 533bcd17cc..bb078f8834 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -294,7 +294,7 @@ void AiSequence::fill(const ESM::AIPackageList &list) idles.reserve(8); for (int i=0; i<8; ++i) idles.push_back(data.mIdle[i]); - package = new MWMechanics::AiWander(data.mDistance, data.mDuration, data.mTimeOfDay, idles, data.mShouldRepeat); + package = new MWMechanics::AiWander(data.mDistance, data.mDuration, data.mTimeOfDay, idles, data.mShouldRepeat != 0); } else if (it->mType == ESM::AI_Escort) { diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index e43ce72f1f..19f1e14545 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -15,7 +15,7 @@ namespace ESM { namespace AiSequence { - class AiSequence; + struct AiSequence; } } diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 7124a1102c..2824e2c6ce 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -93,20 +93,14 @@ namespace MWMechanics mCellX = cell->mData.mX; mCellY = cell->mData.mY; - ESM::Pathgrid::Point dest; - dest.mX = mX; - dest.mY = mY; - dest.mZ = mZ; + ESM::Pathgrid::Point dest(static_cast(mX), static_cast(mY), static_cast(mZ)); - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); mPathFinder.buildPath(start, dest, actor.getCell(), true); } - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) + if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1])) { movement.mPosition[1] = 0; return true; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index fbb147b341..560e756ce2 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include "../mwbase/world.hpp" @@ -29,6 +31,18 @@ namespace MWMechanics static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player static const int GREETING_SHOULD_END = 10; + const std::string AiWander::sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1] = + { + std::string("idle2"), + std::string("idle3"), + std::string("idle4"), + std::string("idle5"), + std::string("idle6"), + std::string("idle7"), + std::string("idle8"), + std::string("idle9"), + }; + /// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive. struct AiWanderStorage : AiTemporaryBase { @@ -192,7 +206,7 @@ namespace MWMechanics if(mDistance && // actor is not intended to be stationary idleNow && // but is in idle !walking && // FIXME: some actors are idle while walking - proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6*1.6)) // NOTE: checks interior cells only + proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only { idleNow = false; moveNow = true; @@ -203,7 +217,7 @@ namespace MWMechanics // Are we there yet? bool& chooseAction = storage.mChooseAction; if(walking && - storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2], 64.f)) + storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], 64.f)) { stopWalking(actor, storage); moveNow = false; @@ -315,13 +329,13 @@ namespace MWMechanics static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore() .get().find("fVoiceIdleOdds")->getFloat(); - float roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 10000; + float roll = OEngine::Misc::Rng::rollProbability() * 10000.0f; // In vanilla MW the chance was FPS dependent, and did not allow proper changing of fVoiceIdleOdds // due to the roll being an integer. // Our implementation does not have these issues, so needs to be recalibrated. We chose to // use the chance MW would have when run at 60 FPS with the default value of the GMST for calibration. - float x = fVoiceIdleOdds * 0.6 * (MWBase::Environment::get().getFrameDuration() / 0.1); + float x = fVoiceIdleOdds * 0.6f * (MWBase::Environment::get().getFrameDuration() / 0.1f); // Only say Idle voices when player is in LOS // A bit counterintuitive, likely vanilla did this to reduce the appearance of @@ -393,18 +407,10 @@ namespace MWMechanics if (!storage.mPathFinder.isPathConstructed()) { - Ogre::Vector3 destNodePos = mReturnPosition; - - ESM::Pathgrid::Point dest; - dest.mX = destNodePos[0]; - dest.mY = destNodePos[1]; - dest.mZ = destNodePos[2]; + ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mReturnPosition)); // actor position is already in world co-ordinates - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); // don't take shortcuts for wandering storage.mPathFinder.buildPath(start, dest, actor.getCell(), false); @@ -422,7 +428,7 @@ namespace MWMechanics { // Play a random voice greeting if the player gets too close int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); - float helloDistance = hello; + float helloDistance = static_cast(hello); static int iGreetDistanceMultiplier =MWBase::Environment::get().getWorld()->getStore() .get().find("iGreetDistanceMultiplier")->getInt(); @@ -498,17 +504,12 @@ namespace MWMechanics if(!storage.mPathFinder.isPathConstructed()) { assert(mAllowedNodes.size()); - unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size()); + unsigned int randNode = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); // NOTE: initially constructed with local (i.e. cell) co-ordinates - Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, - mAllowedNodes[randNode].mY, - mAllowedNodes[randNode].mZ); + Ogre::Vector3 destNodePos(PathFinder::MakeOgreVector3(mAllowedNodes[randNode])); // convert dest to use world co-ordinates - ESM::Pathgrid::Point dest; - dest.mX = destNodePos[0]; - dest.mY = destNodePos[1]; - dest.mZ = destNodePos[2]; + ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(destNodePos)); if (currentCell->getCell()->isExterior()) { dest.mX += currentCell->getCell()->mData.mX * ESM::Land::REAL_SIZE; @@ -516,10 +517,7 @@ namespace MWMechanics } // actor position is already in world co-ordinates - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; + ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); // don't take shortcuts for wandering storage.mPathFinder.buildPath(start, dest, actor.getCell(), false); @@ -594,44 +592,24 @@ namespace MWMechanics void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect) { - if(idleSelect == 2) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle2", 0, 1); - else if(idleSelect == 3) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1); - else if(idleSelect == 4) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle4", 0, 1); - else if(idleSelect == 5) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle5", 0, 1); - else if(idleSelect == 6) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle6", 0, 1); - else if(idleSelect == 7) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle7", 0, 1); - else if(idleSelect == 8) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle8", 0, 1); - else if(idleSelect == 9) - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle9", 0, 1); + if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle)) + { + const std::string& groupName = sIdleSelectToGroupName[idleSelect - GroupIndex_MinIdle]; + MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, groupName, 0, 1); + } } bool AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect) { - if(idleSelect == 2) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle2"); - else if(idleSelect == 3) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle3"); - else if(idleSelect == 4) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle4"); - else if(idleSelect == 5) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle5"); - else if(idleSelect == 6) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle6"); - else if(idleSelect == 7) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle7"); - else if(idleSelect == 8) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle8"); - else if(idleSelect == 9) - return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle9"); + if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle)) + { + const std::string& groupName = sIdleSelectToGroupName[idleSelect - GroupIndex_MinIdle]; + return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, groupName); + } else + { return false; + } } void AiWander::setReturnPosition(const Ogre::Vector3& position) @@ -652,8 +630,8 @@ namespace MWMechanics static float fIdleChanceMultiplier = MWBase::Environment::get().getWorld()->getStore() .get().find("fIdleChanceMultiplier")->getFloat(); - unsigned short idleChance = fIdleChanceMultiplier * mIdle[counter]; - unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / fIdleChanceMultiplier)); + unsigned short idleChance = static_cast(fIdleChanceMultiplier * mIdle[counter]); + unsigned short randSelect = (int)(OEngine::Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier)); if(randSelect < idleChance && randSelect > idleRoll) { playedIdle = counter+2; @@ -675,12 +653,12 @@ namespace MWMechanics state.moveIn(new AiWanderStorage()); - int index = std::rand() / (static_cast (RAND_MAX) + 1) * mAllowedNodes.size(); + int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); ESM::Pathgrid::Point dest = mAllowedNodes[index]; // apply a slight offset to prevent overcrowding - dest.mX += Ogre::Math::RangeRandom(-64, 64); - dest.mY += Ogre::Math::RangeRandom(-64, 64); + dest.mX += static_cast(Ogre::Math::RangeRandom(-64, 64)); + dest.mY += static_cast(Ogre::Math::RangeRandom(-64, 64)); if (actor.getCell()->isExterior()) { @@ -688,7 +666,8 @@ namespace MWMechanics dest.mY += actor.getCell()->getCell()->mData.mY * ESM::Land::REAL_SIZE; } - MWBase::Environment::get().getWorld()->moveObject(actor, dest.mX, dest.mY, dest.mZ); + MWBase::Environment::get().getWorld()->moveObject(actor, static_cast(dest.mX), + static_cast(dest.mY), static_cast(dest.mZ)); actor.getClass().adjustPosition(actor, false); } @@ -707,7 +686,8 @@ namespace MWMechanics // If there is no path this actor doesn't go anywhere. See: // https://forum.openmw.org/viewtopic.php?t=1556 // http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833 - if(!pathgrid || pathgrid->mPoints.empty()) + // Note: In order to wander, need at least two points. + if(!pathgrid || (pathgrid->mPoints.size() < 2)) mDistance = 0; // A distance value passed into the constructor indicates how far the @@ -720,8 +700,8 @@ namespace MWMechanics float cellYOffset = 0; if(cell->isExterior()) { - cellXOffset = cell->mData.mX * ESM::Land::REAL_SIZE; - cellYOffset = cell->mData.mY * ESM::Land::REAL_SIZE; + cellXOffset = static_cast(cell->mData.mX * ESM::Land::REAL_SIZE); + cellYOffset = static_cast(cell->mData.mY * ESM::Land::REAL_SIZE); } // convert npcPos to local (i.e. cell) co-ordinates @@ -733,32 +713,55 @@ namespace MWMechanics // NOTE: mPoints and mAllowedNodes are in local co-ordinates for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) { - Ogre::Vector3 nodePos(pathgrid->mPoints[counter].mX, pathgrid->mPoints[counter].mY, - pathgrid->mPoints[counter].mZ); + Ogre::Vector3 nodePos(PathFinder::MakeOgreVector3(pathgrid->mPoints[counter])); if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance) mAllowedNodes.push_back(pathgrid->mPoints[counter]); } if(!mAllowedNodes.empty()) { - Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ); + Ogre::Vector3 firstNodePos(PathFinder::MakeOgreVector3(mAllowedNodes[0])); float closestNode = npcPos.squaredDistance(firstNodePos); unsigned int index = 0; for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++) { - Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY, - mAllowedNodes[counterThree].mZ); + Ogre::Vector3 nodePos(PathFinder::MakeOgreVector3(mAllowedNodes[counterThree])); float tempDist = npcPos.squaredDistance(nodePos); if(tempDist < closestNode) index = counterThree; } mCurrentNode = mAllowedNodes[index]; mAllowedNodes.erase(mAllowedNodes.begin() + index); - - mStoredAvailableNodes = true; // set only if successful in finding allowed nodes } + + // In vanilla Morrowind, sometimes distance is too small to include at least two points, + // in which case, we will take the two closest points regardless of the wander distance + // This is a backup option, as std::sort is potentially O(n^2) in time. + if (mAllowedNodes.empty()) + { + // Start with list of PathGrid nodes, sorted by distance from actor + std::vector nodeDistances; + for (unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) + { + float distance = npcPos.squaredDistance(PathFinder::MakeOgreVector3(pathgrid->mPoints[counter])); + nodeDistances.push_back(std::make_pair(distance, &pathgrid->mPoints.at(counter))); + } + std::sort(nodeDistances.begin(), nodeDistances.end(), sortByDistance); + + // make closest node the current node + mCurrentNode = *nodeDistances[0].second; + + // give Actor a 2nd node to walk to + mAllowedNodes.push_back(*nodeDistances[1].second); + } + mStoredAvailableNodes = true; // set only if successful in finding allowed nodes } } + bool AiWander::sortByDistance(const PathDistance& left, const PathDistance& right) + { + return left.first < right.first; + } + void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const { std::auto_ptr wander(new ESM::AiSequence::AiWander()); @@ -785,7 +788,7 @@ namespace MWMechanics , mDuration(wander->mData.mDuration) , mStartTime(MWWorld::TimeStamp(wander->mStartTime)) , mTimeOfDay(wander->mData.mTimeOfDay) - , mRepeat(wander->mData.mShouldRepeat) + , mRepeat(wander->mData.mShouldRepeat != 0) , mStoredInitialActorPosition(wander->mStoredInitialActorPosition) { if (mStoredInitialActorPosition) diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 5e1b418139..7f8fc5088a 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -17,7 +17,7 @@ namespace ESM { - class Cell; + struct Cell; namespace AiSequence { struct AiWander; @@ -113,7 +113,22 @@ namespace MWMechanics float mDoorCheckDuration; int mStuckCount; + // constants for converting idleSelect values into groupNames + enum GroupIndex + { + GroupIndex_MinIdle = 2, + GroupIndex_MaxIdle = 9 + }; + /// lookup table for converting idleSelect value to groupName + static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1]; + + /// record distances of pathgrid point nodes to actor + /// first value is distance between actor and node, second value is PathGrid node + typedef std::pair PathDistance; + + /// used to sort array of PathDistance objects into ascending order + static bool sortByDistance(const PathDistance& left, const PathDistance& right); }; diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index f3d376a700..58c42ddb81 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include #include #include @@ -67,7 +69,7 @@ void MWMechanics::Alchemy::applyTools (int flags, float& value) const { bool magnitude = !(flags & ESM::MagicEffect::NoMagnitude); bool duration = !(flags & ESM::MagicEffect::NoDuration); - bool negative = flags & (ESM::MagicEffect::Harmful); + bool negative = (flags & ESM::MagicEffect::Harmful) != 0; int tool = negative ? ESM::Apparatus::Retort : ESM::Apparatus::Albemic; @@ -94,17 +96,17 @@ void MWMechanics::Alchemy::applyTools (int flags, float& value) const quality = negative ? 2 * toolQuality + 3 * calcinatorQuality : (magnitude && duration ? - 2 * toolQuality + calcinatorQuality : 2/3.0 * (toolQuality + calcinatorQuality) + 0.5); + 2 * toolQuality + calcinatorQuality : 2/3.0f * (toolQuality + calcinatorQuality) + 0.5f); break; case 2: - quality = negative ? 1+toolQuality : (magnitude && duration ? toolQuality : toolQuality + 0.5); + quality = negative ? 1+toolQuality : (magnitude && duration ? toolQuality : toolQuality + 0.5f); break; case 3: - quality = magnitude && duration ? calcinatorQuality : calcinatorQuality + 0.5; + quality = magnitude && duration ? calcinatorQuality : calcinatorQuality + 0.5f; break; } @@ -178,8 +180,8 @@ void MWMechanics::Alchemy::updateEffects() if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) applyTools (magicEffect->mData.mFlags, duration); - duration = static_cast (duration+0.5); - magnitude = static_cast (magnitude+0.5); + duration = roundf(duration); + magnitude = roundf(magnitude); if (magnitude>0 && duration>0) { @@ -197,8 +199,8 @@ void MWMechanics::Alchemy::updateEffects() effect.mRange = 0; effect.mArea = 0; - effect.mDuration = duration; - effect.mMagnMin = effect.mMagnMax = magnitude; + effect.mDuration = static_cast(duration); + effect.mMagnMin = effect.mMagnMax = static_cast(magnitude); mEffects.push_back (effect); } @@ -294,7 +296,7 @@ void MWMechanics::Alchemy::addPotion (const std::string& name) newRecord.mName = name; - int index = static_cast (std::rand()/(static_cast (RAND_MAX)+1)*6); + int index = OEngine::Misc::Rng::rollDice(6); assert (index>=0 && index<6); static const char *meshes[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" }; @@ -323,8 +325,8 @@ float MWMechanics::Alchemy::getAlchemyFactor() const return (npcStats.getSkill (ESM::Skill::Alchemy).getModified() + - 0.1 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified() - + 0.1 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()); + 0.1f * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified() + + 0.1f * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()); } int MWMechanics::Alchemy::countIngredients() const @@ -467,7 +469,7 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na return Result_RandomFailure; } - if (getAlchemyFactor() (RAND_MAX)*100) + if (getAlchemyFactor() < OEngine::Misc::Rng::roll0to99()) { removeIngredients(); return Result_RandomFailure; diff --git a/apps/openmw/mwmechanics/autocalcspell.cpp b/apps/openmw/mwmechanics/autocalcspell.cpp index 7b8c43a064..e4b1438260 100644 --- a/apps/openmw/mwmechanics/autocalcspell.cpp +++ b/apps/openmw/mwmechanics/autocalcspell.cpp @@ -187,7 +187,7 @@ namespace MWMechanics for (std::vector::const_iterator it = effects.mList.begin(); it != effects.mList.end(); ++it) { const ESM::ENAMstruct& effect = *it; - float x = effect.mDuration; + float x = static_cast(effect.mDuration); const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effect.mEffectID); if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 449c030f45..ffde59aee6 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -27,6 +27,8 @@ #include "creaturestats.hpp" #include "security.hpp" +#include + #include #include "../mwrender/animation.hpp" @@ -112,7 +114,7 @@ float getFallDamage(const MWWorld::Ptr& ptr, float fallHeight) if (fallHeight >= fallDistanceMin) { - const float acrobaticsSkill = ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics); + const float acrobaticsSkill = static_cast(ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics)); const float jumpSpellBonus = ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude(); const float fallAcroBase = store.find("fFallAcroBase")->getFloat(); const float fallAcroMult = store.find("fFallAcroMult")->getFloat(); @@ -120,7 +122,7 @@ float getFallDamage(const MWWorld::Ptr& ptr, float fallHeight) const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat(); float x = fallHeight - fallDistanceMin; - x -= (1.5 * acrobaticsSkill) + jumpSpellBonus; + x -= (1.5f * acrobaticsSkill) + jumpSpellBonus; x = std::max(0.0f, x); float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill); @@ -220,7 +222,7 @@ std::string CharacterController::chooseRandomGroup (const std::string& prefix, i while (mAnimation->hasAnimation(prefix + Ogre::StringConverter::toString(numAnims+1))) ++numAnims; - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * numAnims + 1; // [1, numAnims] + int roll = OEngine::Misc::Rng::rollDice(numAnims) + 1; // [1, numAnims] if (num) *num = roll; return prefix + Ogre::StringConverter::toString(roll); @@ -829,7 +831,7 @@ bool CharacterController::updateCreatureState() } if (weapType != WeapType_Spell || !mAnimation->hasAnimation("spellcast")) // Not all creatures have a dedicated spellcast animation { - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 3; // [0, 2] + int roll = OEngine::Misc::Rng::rollDice(3); // [0, 2] if (roll == 0) mCurrentWeapon = "attack1"; else if (roll == 1) @@ -1010,7 +1012,7 @@ bool CharacterController::updateWeaponState() // For the player, set the spell we want to cast // This has to be done at the start of the casting animation, // *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation) - if (mPtr.getRefData().getHandle() == "player") + if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell(); stats.getSpells().setSelectedSpell(selectedSpell); @@ -1094,7 +1096,7 @@ bool CharacterController::updateWeaponState() mAttackType = "shoot"; else { - if(isWeapon && mPtr.getRefData().getHandle() == "player" && + if(isWeapon && mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr() && Settings::Manager::getBool("best attack", "Game")) { MWWorld::ContainerStoreIterator weapon = mPtr.getClass().getInventoryStore(mPtr).getSlot(MWWorld::InventoryStore::Slot_CarriedRight); @@ -1125,7 +1127,7 @@ bool CharacterController::updateWeaponState() // most creatures don't actually have an attack wind-up animation, so use a uniform random value // (even some creatures that can use weapons don't have a wind-up animation either, e.g. Rieklings) // Note: vanilla MW uses a random value for *all* non-player actors, but we probably don't need to go that far. - attackStrength = std::min(1.f, 0.1f + std::rand() / float(RAND_MAX)); + attackStrength = std::min(1.f, 0.1f + OEngine::Misc::Rng::rollClosedProbability()); } if(mWeaponType != WeapType_Crossbow && mWeaponType != WeapType_BowAndArrow) @@ -1421,7 +1423,7 @@ void CharacterController::update(float duration) // advance athletics - if(mHasMovedInXY && mPtr.getRefData().getHandle() == "player") + if(mHasMovedInXY && mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { if(inwater) { @@ -1521,7 +1523,7 @@ void CharacterController::update(float duration) } // advance acrobatics - if (mPtr.getRefData().getHandle() == "player") + if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); // decrease fatigue @@ -1531,7 +1533,7 @@ void CharacterController::update(float duration) float normalizedEncumbrance = mPtr.getClass().getNormalizedEncumbrance(mPtr); if (normalizedEncumbrance > 1) normalizedEncumbrance = 1; - const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; + const float fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult; DynamicStat fatigue = cls.getCreatureStats(mPtr).getFatigue(); fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); cls.getCreatureStats(mPtr).setFatigue(fatigue); @@ -1551,12 +1553,12 @@ void CharacterController::update(float duration) // inflict fall damages DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); - int realHealthLost = healthLost * (1.0f - 0.25 * fatigueTerm); + float realHealthLost = static_cast(healthLost * (1.0f - 0.25f * fatigueTerm)); health.setCurrent(health.getCurrent() - realHealthLost); cls.getCreatureStats(mPtr).setHealth(health); cls.onHit(mPtr, realHealthLost, true, MWWorld::Ptr(), MWWorld::Ptr(), true); - const float acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics); + const int acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics); if (healthLost > (acrobaticsSkill * fatigueTerm)) { cls.getCreatureStats(mPtr).setKnockedDown(true); @@ -1564,7 +1566,7 @@ void CharacterController::update(float duration) else { // report acrobatics progression - if (mPtr.getRefData().getHandle() == "player") + if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); } } @@ -1612,7 +1614,7 @@ void CharacterController::update(float duration) mTurnAnimationThreshold -= duration; if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft) - mTurnAnimationThreshold = 0.05; + mTurnAnimationThreshold = 0.05f; else if (movestate == CharState_None && (mMovementState == CharState_TurnRight || mMovementState == CharState_TurnLeft) && mTurnAnimationThreshold > 0) { @@ -1797,7 +1799,7 @@ bool CharacterController::kill() { if( isDead() ) { - if( mPtr.getRefData().getHandle()=="player" && !isAnimPlaying(mCurrentDeath) ) + if( mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr() && !isAnimPlaying(mCurrentDeath) ) { //player's death animation is over MWBase::Environment::get().getStateManager()->askLoadRecent(); @@ -1813,7 +1815,7 @@ bool CharacterController::kill() mCurrentIdle.clear(); // Play Death Music if it was the player dying - if(mPtr.getRefData().getHandle()=="player") + if(mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Death.mp3"); return true; @@ -1854,7 +1856,7 @@ void CharacterController::updateMagicEffects() float alpha = 1.f; if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude()) { - if (mPtr.getRefData().getHandle() == "player") + if (mPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) alpha = 0.4f; else alpha = 0.f; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 8a77494b97..da74b2a33f 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -21,7 +21,7 @@ namespace MWRender namespace MWMechanics { -class Movement; +struct Movement; class CreatureStats; enum Priority { diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index e22e9ec24f..c5fc34507b 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -2,6 +2,8 @@ #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -83,8 +85,8 @@ namespace MWMechanics MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); - float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() - + 0.1 * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); + float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2f * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() + + 0.1f * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); float enemySwing = attackerStats.getAttackStrength(); float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat(); @@ -93,13 +95,13 @@ namespace MWMechanics blockerTerm *= gmst.find("fBlockStillBonus")->getFloat(); blockerTerm *= blockerStats.getFatigueTerm(); - float attackerSkill = 0.f; + int attackerSkill = 0; if (weapon.isEmpty()) attackerSkill = attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand); else attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); - float attackerTerm = attackerSkill + 0.2 * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() - + 0.1 * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); + float attackerTerm = attackerSkill + 0.2f * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() + + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); attackerTerm *= attackerStats.getFatigueTerm(); int x = int(blockerTerm - attackerTerm); @@ -107,8 +109,7 @@ namespace MWMechanics int iBlockMinChance = gmst.find("iBlockMinChance")->getInt(); x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x)); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (roll < x) + if (OEngine::Misc::Rng::roll0to99() < x) { // Reduce shield durability by incoming damage int shieldhealth = shield->getClass().getItemHealth(*shield); @@ -133,7 +134,7 @@ namespace MWMechanics blockerStats.setBlock(true); - if (blocker.getCellRef().getRefId() == "player") + if (blocker == MWBase::Environment::get().getWorld()->getPlayerPtr()) blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); return true; @@ -157,7 +158,7 @@ namespace MWMechanics && actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()) damage *= MWBase::Environment::get().getWorld()->getStore().get().find("fWereWolfSilverWeaponDamageMult")->getFloat(); - if (damage == 0 && attacker.getRefData().getHandle() == "player") + if (damage == 0 && attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResistsWeapons}"); } @@ -176,42 +177,36 @@ namespace MWMechanics return; } - if(attacker.getRefData().getHandle() == "player") + if(attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->setEnemy(victim); int weapskill = ESM::Skill::Marksman; if(!weapon.isEmpty()) weapskill = weapon.getClass().getEquipmentSkill(weapon); - float skillValue = attacker.getClass().getSkill(attacker, + int skillValue = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); - if((::rand()/(RAND_MAX+1.0)) > getHitChance(attacker, victim, skillValue)/100.0f) + if (OEngine::Misc::Rng::rollProbability() >= getHitChance(attacker, victim, skillValue) / 100.0f) { victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker); return; } - float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat(); - float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat(); const unsigned char* attack = weapon.get()->mBase->mData.mChop; float damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage - if (weapon != projectile) - { - // Arrow/bolt damage - attack = projectile.get()->mBase->mData.mChop; - damage += attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); - } - damage *= fDamageStrengthBase + - (attackerStats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1); + // Arrow/bolt damage + // NB in case of thrown weapons, we are applying the damage twice since projectile == weapon + attack = projectile.get()->mBase->mData.mChop; + damage += attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); - adjustWeaponDamage(damage, weapon); + adjustWeaponDamage(damage, weapon, attacker); reduceWeaponCondition(damage, true, weapon, attacker); - if(attacker.getRefData().getHandle() == "player") + if(attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0); if (victim.getClass().getCreatureStats(victim).getKnockedDown()) @@ -230,7 +225,7 @@ namespace MWMechanics && !appliedEnchantment) { float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat(); - if ((::rand()/(RAND_MAX+1.0)) < fProjectileThrownStoreChance/100.f) + if (OEngine::Misc::Rng::rollProbability() < fProjectileThrownStoreChance / 100.f) victim.getClass().getContainerStore(victim).add(projectile, 1, victim); } @@ -241,14 +236,39 @@ namespace MWMechanics { MWMechanics::CreatureStats &stats = attacker.getClass().getCreatureStats(attacker); const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects(); - float hitchance = skillValue + + + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Store &gmst = world->getStore().get(); + + float defenseTerm = 0; + if (victim.getClass().getCreatureStats(victim).getFatigue().getCurrent() >= 0) + { + MWMechanics::CreatureStats& victimStats = victim.getClass().getCreatureStats(victim); + // Maybe we should keep an aware state for actors updated every so often instead of testing every time + bool unaware = (!victimStats.getAiSequence().isInCombat()) + && (attacker == MWBase::Environment::get().getWorld()->getPlayerPtr()) + && (!MWBase::Environment::get().getMechanicsManager()->awarenessCheck(attacker, victim)); + if (!(victimStats.getKnockedDown() || + victimStats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0 + || unaware )) + { + defenseTerm = victimStats.getEvasion(); + } + defenseTerm += std::min(100.f, + gmst.find("fCombatInvisoMult")->getFloat() * + victimStats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude()); + defenseTerm += std::min(100.f, + gmst.find("fCombatInvisoMult")->getFloat() * + victimStats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude()); + } + float attackTerm = skillValue + (stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) + (stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f); - hitchance *= stats.getFatigueTerm(); - hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).getMagnitude() - + attackTerm *= stats.getFatigueTerm(); + attackTerm += mageffects.get(ESM::MagicEffect::FortifyAttack).getMagnitude() - mageffects.get(ESM::MagicEffect::Blind).getMagnitude(); - hitchance -= victim.getClass().getCreatureStats(victim).getEvasion(); - return hitchance; + + return round(attackTerm - defenseTerm); } void applyElementalShields(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim) @@ -265,15 +285,14 @@ namespace MWMechanics + 0.2f * attackerStats.getAttribute(ESM::Attribute::Willpower).getModified() + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); - int fatigueMax = attackerStats.getFatigue().getModified(); - int fatigueCurrent = attackerStats.getFatigue().getCurrent(); + float fatigueMax = attackerStats.getFatigue().getModified(); + float fatigueCurrent = attackerStats.getFatigue().getCurrent(); - float normalisedFatigue = fatigueMax==0 ? 1 : std::max (0.0f, static_cast (fatigueCurrent)/fatigueMax); + float normalisedFatigue = floor(fatigueMax)==0 ? 1 : std::max (0.0f, (fatigueCurrent/fatigueMax)); saveTerm *= 1.25f * normalisedFatigue; - float roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - float x = std::max(0.f, saveTerm - roll); + float x = std::max(0.f, saveTerm - OEngine::Misc::Rng::roll0to99()); int element = ESM::MagicEffect::FireDamage; if (i == 1) @@ -322,7 +341,7 @@ namespace MWMechanics } } - void adjustWeaponDamage(float &damage, const MWWorld::Ptr &weapon) + void adjustWeaponDamage(float &damage, const MWWorld::Ptr &weapon, const MWWorld::Ptr& attacker) { if (weapon.isEmpty()) return; @@ -334,6 +353,13 @@ namespace MWMechanics int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon); damage *= (float(weaphealth) / weapmaxhealth); } + + static const float fDamageStrengthBase = MWBase::Environment::get().getWorld()->getStore().get() + .find("fDamageStrengthBase")->getFloat(); + static const float fDamageStrengthMult = MWBase::Environment::get().getWorld()->getStore().get() + .find("fDamageStrengthMult")->getFloat(); + damage *= fDamageStrengthBase + + (attacker.getClass().getCreatureStats(attacker).getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1f); } void getHandToHandDamage(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, float &damage, bool &healthdmg) @@ -344,7 +370,7 @@ namespace MWMechanics const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); float minstrike = store.get().find("fMinHandToHandMult")->getFloat(); float maxstrike = store.get().find("fMaxHandToHandMult")->getFloat(); - damage = attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand); + damage = static_cast(attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand)); damage *= minstrike + ((maxstrike-minstrike)*attacker.getClass().getCreatureStats(attacker).getAttackStrength()); MWMechanics::CreatureStats& otherstats = victim.getClass().getCreatureStats(victim); diff --git a/apps/openmw/mwmechanics/combat.hpp b/apps/openmw/mwmechanics/combat.hpp index a48dcf72a4..a2fd8b0067 100644 --- a/apps/openmw/mwmechanics/combat.hpp +++ b/apps/openmw/mwmechanics/combat.hpp @@ -30,7 +30,7 @@ void applyElementalShields(const MWWorld::Ptr& attacker, const MWWorld::Ptr& vic void reduceWeaponCondition (float damage, bool hit, MWWorld::Ptr& weapon, const MWWorld::Ptr& attacker); /// Adjust weapon damage based on its condition. A used weapon will be less effective. -void adjustWeaponDamage (float& damage, const MWWorld::Ptr& weapon); +void adjustWeaponDamage (float& damage, const MWWorld::Ptr& weapon, const MWWorld::Ptr& attacker); void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, float& damage, bool& healthdmg); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 05ea9fb5e4..4c338e23fc 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -42,10 +42,10 @@ namespace MWMechanics float CreatureStats::getFatigueTerm() const { - int max = getFatigue().getModified(); - int current = getFatigue().getCurrent(); + float max = getFatigue().getModified(); + float current = getFatigue().getCurrent(); - float normalised = max==0 ? 1 : std::max (0.0f, static_cast (current)/max); + float normalised = floor(max) == 0 ? 1 : std::max (0.0f, current / max); const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -336,7 +336,7 @@ namespace MWMechanics float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) + (getAttribute(ESM::Attribute::Luck).getModified() / 10.0f); evasion *= getFatigueTerm(); - evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).getMagnitude(); + evasion += std::min(100.f, mMagicEffects.get(ESM::MagicEffect::Sanctuary).getMagnitude()); return evasion; } @@ -439,7 +439,7 @@ namespace MWMechanics bool CreatureStats::getMovementFlag (Flag flag) const { - return mMovementFlags & flag; + return (mMovementFlags & flag) != 0; } void CreatureStats::setMovementFlag (Flag flag, bool state) diff --git a/apps/openmw/mwmechanics/disease.hpp b/apps/openmw/mwmechanics/disease.hpp index a973c0e353..0153be3dc8 100644 --- a/apps/openmw/mwmechanics/disease.hpp +++ b/apps/openmw/mwmechanics/disease.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_MECHANICS_DISEASE_H #define OPENMW_MECHANICS_DISEASE_H +#include + #include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -37,21 +39,19 @@ namespace MWMechanics float resist = 0.f; if (spells.hasCorprusEffect(spell)) - resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude() + resist = 1.f - 0.01f * (actorEffects.get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude() - actorEffects.get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude()); else if (spell->mData.mType == ESM::Spell::ST_Disease) - resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistCommonDisease).getMagnitude() + resist = 1.f - 0.01f * (actorEffects.get(ESM::MagicEffect::ResistCommonDisease).getMagnitude() - actorEffects.get(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude()); else if (spell->mData.mType == ESM::Spell::ST_Blight) - resist = 1.f - 0.01 * (actorEffects.get(ESM::MagicEffect::ResistBlightDisease).getMagnitude() + resist = 1.f - 0.01f * (actorEffects.get(ESM::MagicEffect::ResistBlightDisease).getMagnitude() - actorEffects.get(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude()); else continue; - int x = fDiseaseXferChance * 100 * resist; - float roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 10000; // [0, 9999] - - if (roll < x) + int x = static_cast(fDiseaseXferChance * 100 * resist); + if (OEngine::Misc::Rng::rollDice(10000) < x) { // Contracted disease! actor.getClass().getCreatureStats(actor).getSpells().add(it->first); diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index de5921a702..bb02fb41d3 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -1,4 +1,7 @@ #include "enchanting.hpp" + +#include + #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" @@ -67,7 +70,7 @@ namespace MWMechanics if(mSelfEnchanting) { - if(getEnchantChance() (RAND_MAX)*100) + if(getEnchantChance() <= (OEngine::Misc::Rng::roll0to99())) return false; mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2); @@ -176,7 +179,7 @@ namespace MWMechanics int magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax; int area = (it->mArea == 0) ? 1 : it->mArea; - float magnitudeCost = (magMin + magMax) * baseCost * 0.05; + float magnitudeCost = (magMin + magMax) * baseCost * 0.05f; if (mCastStyle == ESM::Enchantment::ConstantEffect) { magnitudeCost *= store.get().find("fEnchantmentConstantDurationMult")->getFloat(); @@ -186,7 +189,7 @@ namespace MWMechanics magnitudeCost *= it->mDuration; } - float areaCost = area * 0.05 * baseCost; + float areaCost = area * 0.05f * baseCost; const float fEffectCostMult = store.get().find("fEffectCostMult")->getFloat(); @@ -215,7 +218,7 @@ namespace MWMechanics { int baseCost = getBaseCastCost(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - return getEffectiveEnchantmentCastCost(baseCost, player); + return getEffectiveEnchantmentCastCost(static_cast(baseCost), player); } @@ -225,7 +228,7 @@ namespace MWMechanics return 0; float priceMultipler = MWBase::Environment::get().getWorld()->getStore().get().find ("fEnchantmentValueMult")->getFloat(); - int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mEnchanter, (getEnchantPoints() * priceMultipler), true); + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mEnchanter, static_cast(getEnchantPoints() * priceMultipler), true); return price; } @@ -247,7 +250,7 @@ namespace MWMechanics const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - return mOldItemPtr.getClass().getEnchantmentPoints(mOldItemPtr) * store.get().find("fEnchantmentMult")->getFloat(); + return static_cast(mOldItemPtr.getClass().getEnchantmentPoints(mOldItemPtr) * store.get().find("fEnchantmentMult")->getFloat()); } bool Enchanting::soulEmpty() const { @@ -274,13 +277,13 @@ namespace MWMechanics const NpcStats& npcStats = mEnchanter.getClass().getNpcStats (mEnchanter); float chance1 = (npcStats.getSkill (ESM::Skill::Enchant).getModified() + - (0.25 * npcStats.getAttribute (ESM::Attribute::Intelligence).getModified()) - + (0.125 * npcStats.getAttribute (ESM::Attribute::Luck).getModified())); + (0.25f * npcStats.getAttribute (ESM::Attribute::Intelligence).getModified()) + + (0.125f * npcStats.getAttribute (ESM::Attribute::Luck).getModified())); const MWWorld::Store& gmst = MWBase::Environment::get().getWorld()->getStore().get(); - float chance2 = 7.5 / (gmst.find("fEnchantmentChanceMult")->getFloat() * ((mCastStyle == ESM::Enchantment::ConstantEffect) ? - gmst.find("fEnchantmentConstantChanceMult")->getFloat() : 1 )) + float chance2 = 7.5f / (gmst.find("fEnchantmentChanceMult")->getFloat() * ((mCastStyle == ESM::Enchantment::ConstantEffect) ? + gmst.find("fEnchantmentConstantChanceMult")->getFloat() : 1.0f )) * getEnchantPoints(); return (chance1-chance2); diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 691996410c..20b87a3a96 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_MECHANICS_LEVELLEDLIST_H #define OPENMW_MECHANICS_LEVELLEDLIST_H +#include + #include "../mwworld/ptr.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/manualref.hpp" @@ -22,8 +24,7 @@ namespace MWMechanics failChance += levItem->mChanceNone; - int random = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (random < failChance) + if (OEngine::Misc::Rng::roll0to99() < failChance) return std::string(); std::vector candidates; @@ -35,7 +36,7 @@ namespace MWMechanics } // For levelled creatures, the flags are swapped. This file format just makes so much sense. - bool allLevels = levItem->mFlags & ESM::ItemLevList::AllLevels; + bool allLevels = (levItem->mFlags & ESM::ItemLevList::AllLevels) != 0; if (creature) allLevels = levItem->mFlags & ESM::CreatureLevList::AllLevels; @@ -52,7 +53,7 @@ namespace MWMechanics } if (candidates.empty()) return std::string(); - std::string item = candidates[std::rand()%candidates.size()]; + std::string item = candidates[OEngine::Misc::Rng::rollDice(candidates.size())]; // Vanilla doesn't fail on nonexistent items in levelled lists if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 4e4a1a8a69..0d4518f875 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -2,6 +2,8 @@ #include "mechanicsmanagerimp.hpp" #include "npcstats.hpp" +#include + #include #include "../mwworld/esmstore.hpp" @@ -556,7 +558,7 @@ namespace MWMechanics int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr) { const MWMechanics::NpcStats& npcSkill = ptr.getClass().getNpcStats(ptr); - float x = npcSkill.getBaseDisposition(); + float x = static_cast(npcSkill.getBaseDisposition()); MWWorld::LiveCellRef* npc = ptr.get(); MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); @@ -583,7 +585,7 @@ namespace MWMechanics if (!playerStats.getExpelled(npcFaction)) { // faction reaction towards itself. yes, that exists - reaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, npcFaction); + reaction = static_cast(MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, npcFaction)); rank = playerStats.getFactionRanks().find(npcFaction)->second; } @@ -597,7 +599,7 @@ namespace MWMechanics int itReaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(npcFaction, itFaction); if (playerFactionIt == playerStats.getFactionRanks().begin() || itReaction < reaction) - reaction = itReaction; + reaction = static_cast(itReaction); } } else @@ -643,17 +645,17 @@ namespace MWMechanics // otherwise one would get different prices when exiting and re-entering the dialogue window... int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr) + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100)); - float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float a = static_cast(std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100)); float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); - float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float d = static_cast(std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100)); float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); float pcTerm = (clampedDisposition - 50 + a + b + c) * playerStats.getFatigueTerm(); float npcTerm = (d + e + f) * sellerStats.getFatigueTerm(); - float buyTerm = 0.01 * (100 - 0.5 * (pcTerm - npcTerm)); - float sellTerm = 0.01 * (50 - 0.5 * (npcTerm - pcTerm)); + float buyTerm = 0.01f * (100 - 0.5f * (pcTerm - npcTerm)); + float sellTerm = 0.01f * (50 - 0.5f * (npcTerm - pcTerm)); float x; if(buying) x = buyTerm; @@ -704,7 +706,7 @@ namespace MWMechanics int currentDisposition = std::min(100, std::max(0, int(getDerivedDisposition(npc) + currentTemporaryDispositionDelta))); - float d = 1 - 0.02 * abs(currentDisposition - 50); + float d = 1 - 0.02f * abs(currentDisposition - 50); float target1 = d * (playerRating1 - npcRating1 + 50); float target2 = d * (playerRating2 - npcRating2 + 50); @@ -715,21 +717,21 @@ namespace MWMechanics float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod; - float iPerMinChance = gmst.find("iPerMinChance")->getInt(); - float iPerMinChange = gmst.find("iPerMinChange")->getInt(); + float iPerMinChance = floor(gmst.find("iPerMinChance")->getFloat()); + float iPerMinChange = floor(gmst.find("iPerMinChange")->getFloat()); float fPerDieRollMult = gmst.find("fPerDieRollMult")->getFloat(); float fPerTempMult = gmst.find("fPerTempMult")->getFloat(); float x = 0; float y = 0; - float roll = static_cast (std::rand()) / RAND_MAX * 100; + float roll = OEngine::Misc::Rng::rollClosedProbability() * 100; if (type == PT_Admire) { target1 = std::max(iPerMinChance, target1); success = (roll <= target1); - float c = int(fPerDieRollMult * (target1 - roll)); + float c = floor(fPerDieRollMult * (target1 - roll)); x = success ? std::max(iPerMinChange, c) : c; } else if (type == PT_Intimidate) @@ -740,13 +742,13 @@ namespace MWMechanics float r; if (roll != target2) - r = int(target2 - roll); + r = floor(target2 - roll); else r = 1; if (roll <= target2) { - float s = int(r * fPerDieRollMult * fPerTempMult); + float s = floor(r * fPerDieRollMult * fPerTempMult); int flee = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Flee).getBase(); int fight = npcStats.getAiSetting(MWMechanics::CreatureStats::AI_Fight).getBase(); @@ -756,7 +758,7 @@ namespace MWMechanics std::max(0, std::min(100, fight + int(std::min(-iPerMinChange, -s))))); } - float c = -std::abs(int(r * fPerDieRollMult)); + float c = -std::abs(floor(r * fPerDieRollMult)); if (success) { if (std::abs(c) < iPerMinChange) @@ -766,13 +768,13 @@ namespace MWMechanics } else { - x = -int(c * fPerTempMult); + x = -floor(c * fPerTempMult); y = c; } } else { - x = int(c * fPerTempMult); + x = floor(c * fPerTempMult); y = c; } } @@ -781,7 +783,7 @@ namespace MWMechanics target1 = std::max(iPerMinChance, target1); success = (roll <= target1); - float c = std::abs(int(target1 - roll)); + float c = std::abs(floor(target1 - roll)); if (success) { @@ -793,7 +795,7 @@ namespace MWMechanics npcStats.setAiSetting (CreatureStats::AI_Fight, std::max(0, std::min(100, fight + std::max(int(iPerMinChange), int(s))))); } - x = int(-c * fPerDieRollMult); + x = floor(-c * fPerDieRollMult); if (success && std::abs(x) < iPerMinChange) x = -iPerMinChange; @@ -802,7 +804,7 @@ namespace MWMechanics { target3 = std::max(iPerMinChance, target3); success = (roll <= target3); - float c = int((target3 - roll) * fPerDieRollMult); + float c = floor((target3 - roll) * fPerDieRollMult); x = success ? std::max(iPerMinChange, c) : c; } @@ -812,11 +814,11 @@ namespace MWMechanics float cappedDispositionChange = tempChange; if (currentDisposition + tempChange > 100.f) - cappedDispositionChange = 100 - currentDisposition; + cappedDispositionChange = static_cast(100 - currentDisposition); if (currentDisposition + tempChange < 0.f) - cappedDispositionChange = -currentDisposition; + cappedDispositionChange = static_cast(-currentDisposition); - permChange = int(cappedDispositionChange / fPerTempMult); + permChange = floor(cappedDispositionChange / fPerTempMult); if (type == PT_Intimidate) { permChange = success ? -int(cappedDispositionChange/ fPerTempMult) : y; @@ -1104,7 +1106,7 @@ namespace MWMechanics if (type == OT_Trespassing || type == OT_SleepingInOwnedBed) { arg = store.find("iCrimeTresspass")->getInt(); - disp = dispVictim = store.find("iDispTresspass")->getInt(); + disp = dispVictim = store.find("iDispTresspass")->getFloat(); } else if (type == OT_Pickpocket) { @@ -1114,18 +1116,18 @@ namespace MWMechanics else if (type == OT_Assault) { arg = store.find("iCrimeAttack")->getInt(); - disp = store.find("iDispAttackMod")->getInt(); + disp = store.find("iDispAttackMod")->getFloat(); dispVictim = store.find("fDispAttacking")->getFloat(); } else if (type == OT_Murder) { arg = store.find("iCrimeKilling")->getInt(); - disp = dispVictim = store.find("iDispKilling")->getInt(); + disp = dispVictim = store.find("iDispKilling")->getFloat(); } else if (type == OT_Theft) { disp = dispVictim = store.find("fDispStealing")->getFloat() * arg; - arg *= store.find("fCrimeStealing")->getFloat(); + arg = static_cast(arg * store.find("fCrimeStealing")->getFloat()); arg = std::max(1, arg); // Minimum bounty of 1, in case items with zero value are stolen } @@ -1163,7 +1165,7 @@ namespace MWMechanics else if (type == OT_Murder) fight = fightVictim = esmStore.get().find("iFightKilling")->getInt(); else if (type == OT_Theft) - fight = fightVictim = esmStore.get().find("fFightStealing")->getFloat(); + fight = fightVictim = esmStore.get().find("fFightStealing")->getInt(); bool reported = false; @@ -1197,21 +1199,21 @@ namespace MWMechanics { float dispTerm = (*it == victim) ? dispVictim : disp; - float alarmTerm = 0.01 * it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase(); + float alarmTerm = 0.01f * it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase(); if (type == OT_Pickpocket && alarmTerm <= 0) alarmTerm = 1.0; if (*it != victim) dispTerm *= alarmTerm; - float fightTerm = (*it == victim) ? fightVictim : fight; + float fightTerm = static_cast((*it == victim) ? fightVictim : fight); fightTerm += getFightDispositionBias(dispTerm); fightTerm += getFightDistanceBias(*it, player); fightTerm *= alarmTerm; int observerFightRating = it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Fight).getBase(); if (observerFightRating + fightTerm > 100) - fightTerm = 100 - observerFightRating; + fightTerm = static_cast(100 - observerFightRating); fightTerm = std::max(0.f, fightTerm); if (observerFightRating + fightTerm >= 100) @@ -1221,9 +1223,9 @@ namespace MWMechanics NpcStats& observerStats = it->getClass().getNpcStats(*it); // Apply aggression value to the base Fight rating, so that the actor can continue fighting // after a Calm spell wears off - observerStats.setAiSetting(CreatureStats::AI_Fight, observerFightRating + fightTerm); + observerStats.setAiSetting(CreatureStats::AI_Fight, observerFightRating + static_cast(fightTerm)); - observerStats.setBaseDisposition(observerStats.getBaseDisposition()+dispTerm); + observerStats.setBaseDisposition(observerStats.getBaseDisposition() + static_cast(dispTerm)); // Set the crime ID, which we will use to calm down participants // once the bounty has been paid. @@ -1334,7 +1336,7 @@ namespace MWMechanics { static float fSneakSkillMult = store.find("fSneakSkillMult")->getFloat(); static float fSneakBootMult = store.find("fSneakBootMult")->getFloat(); - float sneak = ptr.getClass().getSkill(ptr, ESM::Skill::Sneak); + float sneak = static_cast(ptr.getClass().getSkill(ptr, ESM::Skill::Sneak)); int agility = stats.getAttribute(ESM::Attribute::Agility).getModified(); int luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); float bootWeight = 0; @@ -1345,7 +1347,7 @@ namespace MWMechanics if (it != inv.end()) bootWeight = it->getClass().getWeight(*it); } - sneakTerm = fSneakSkillMult * sneak + 0.2 * agility + 0.1 * luck + bootWeight * fSneakBootMult; + sneakTerm = fSneakSkillMult * sneak + 0.2f * agility + 0.1f * luck + bootWeight * fSneakBootMult; } static float fSneakDistBase = store.find("fSneakDistanceBase")->getFloat(); @@ -1364,7 +1366,7 @@ namespace MWMechanics float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); int obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak); - float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind; + float obsTerm = obsSneak + 0.2f * obsAgility + 0.1f * obsLuck - obsBlind; // is ptr behind the observer? static float fSneakNoViewMult = store.find("fSneakNoViewMult")->getFloat(); @@ -1378,9 +1380,8 @@ namespace MWMechanics y = obsTerm * observerStats.getFatigueTerm() * fSneakViewMult; float target = x - y; - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - return (roll >= target); + return (OEngine::Misc::Rng::roll0to99() >= target); } void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) @@ -1479,9 +1480,8 @@ namespace MWMechanics if (ptr.getClass().isNpc()) disposition = getDerivedDisposition(ptr); - int fight = std::max(0.f, ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified() - + getFightDistanceBias(ptr, target) - + getFightDispositionBias(disposition)); + int fight = std::max(0, ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified() + + static_cast(getFightDistanceBias(ptr, target) + getFightDispositionBias(static_cast(disposition)))); if (ptr.getClass().isNpc() && target.getClass().isNpc()) { diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 58bf11cfff..7f468f6d41 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -142,7 +142,7 @@ void MWMechanics::NpcStats::setFactionReputation (const std::string& faction, in float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const ESM::Class& class_) const { - float progressRequirement = 1 + getSkill (skillIndex).getBase(); + float progressRequirement = static_cast(1 + getSkill(skillIndex).getBase()); const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -303,7 +303,7 @@ void MWMechanics::NpcStats::updateHealth() const int endurance = getAttribute(ESM::Attribute::Endurance).getBase(); const int strength = getAttribute(ESM::Attribute::Strength).getBase(); - setHealth(static_cast (0.5 * (strength + endurance))); + setHealth(floor(0.5f * (strength + endurance))); } int MWMechanics::NpcStats::getLevelupAttributeMultiplier(int attribute) const diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 0634725a81..5795f818af 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -17,7 +17,7 @@ namespace // float distanceSquared(ESM::Pathgrid::Point point, Ogre::Vector3 pos) { - return Ogre::Vector3(point.mX, point.mY, point.mZ).squaredDistance(pos); + return MWMechanics::PathFinder::MakeOgreVector3(point).squaredDistance(pos); } // Return the closest pathgrid point index from the specified position co @@ -90,12 +90,11 @@ namespace namespace MWMechanics { - float sqrDistanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z) + float sqrDistanceIgnoreZ(ESM::Pathgrid::Point point, float x, float y) { x -= point.mX; y -= point.mY; - z -= point.mZ; - return (x * x + y * y + 0.1 * z * z); + return (x * x + y * y); } float distance(ESM::Pathgrid::Point point, float x, float y, float z) @@ -108,9 +107,9 @@ namespace MWMechanics float distance(ESM::Pathgrid::Point a, ESM::Pathgrid::Point b) { - float x = a.mX - b.mX; - float y = a.mY - b.mY; - float z = a.mZ - b.mZ; + float x = static_cast(a.mX - b.mX); + float y = static_cast(a.mY - b.mY); + float z = static_cast(a.mZ - b.mZ); return sqrt(x * x + y * y + z * z); } @@ -176,8 +175,9 @@ namespace MWMechanics if(allowShortcuts) { // if there's a ray cast hit, can't take a direct path - if(!MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, - endPoint.mX, endPoint.mY, endPoint.mZ)) + if (!MWBase::Environment::get().getWorld()->castRay( + static_cast(startPoint.mX), static_cast(startPoint.mY), static_cast(startPoint.mZ), + static_cast(endPoint.mX), static_cast(endPoint.mY), static_cast(endPoint.mZ))) { mPath.push_back(endPoint); mIsPathConstructed = true; @@ -206,8 +206,8 @@ namespace MWMechanics float yCell = 0; if (mCell->isExterior()) { - xCell = mCell->getCell()->mData.mX * ESM::Land::REAL_SIZE; - yCell = mCell->getCell()->mData.mY * ESM::Land::REAL_SIZE; + xCell = static_cast(mCell->getCell()->mData.mX * ESM::Land::REAL_SIZE); + yCell = static_cast(mCell->getCell()->mData.mY * ESM::Land::REAL_SIZE); } // NOTE: It is possible that getClosestPoint returns a pathgrind point index @@ -216,12 +216,12 @@ namespace MWMechanics // point right behind the wall that is closer than any pathgrid // point outside the wall int startNode = getClosestPoint(mPathgrid, - Ogre::Vector3(startPoint.mX - xCell, startPoint.mY - yCell, startPoint.mZ)); + Ogre::Vector3(startPoint.mX - xCell, startPoint.mY - yCell, static_cast(startPoint.mZ))); // Some cells don't have any pathgrids at all if(startNode != -1) { std::pair endNode = getClosestReachablePoint(mPathgrid, cell, - Ogre::Vector3(endPoint.mX - xCell, endPoint.mY - yCell, endPoint.mZ), + Ogre::Vector3(endPoint.mX - xCell, endPoint.mY - yCell, static_cast(endPoint.mZ)), startNode); // this shouldn't really happen, but just in case @@ -282,13 +282,13 @@ namespace MWMechanics return Ogre::Math::ATan2(directionX,directionY).valueDegrees(); } - bool PathFinder::checkPathCompleted(float x, float y, float z, float tolerance) + bool PathFinder::checkPathCompleted(float x, float y, float tolerance) { if(mPath.empty()) return true; ESM::Pathgrid::Point nextPoint = *mPath.begin(); - if(sqrDistanceZCorrected(nextPoint, x, y, z) < tolerance*tolerance) + if (sqrDistanceIgnoreZ(nextPoint, x, y) < tolerance*tolerance) { mPath.pop_front(); if(mPath.empty()) diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 7ba2d22ba6..f48de6624c 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -1,10 +1,12 @@ #ifndef GAME_MWMECHANICS_PATHFINDING_H #define GAME_MWMECHANICS_PATHFINDING_H +#include #include #include #include +#include namespace MWWorld { @@ -27,11 +29,11 @@ namespace MWMechanics return -1.0; } - static float sgn(float a) + static int sgn(int a) { if(a > 0) - return 1.0; - return -1.0; + return 1; + return -1; } void clearPath(); @@ -39,7 +41,7 @@ namespace MWMechanics void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, const MWWorld::CellStore* cell, bool allowShortcuts = true); - bool checkPathCompleted(float x, float y, float z, float tolerance=32.f); + bool checkPathCompleted(float x, float y, float tolerance=32.f); ///< \Returns true if we are within \a tolerance units of the last path point. float getZAngleToNext(float x, float y) const; @@ -74,6 +76,24 @@ namespace MWMechanics mPath.push_back(point); } + /// utility function to convert a Ogre::Vector3 to a Pathgrid::Point + static ESM::Pathgrid::Point MakePathgridPoint(const Ogre::Vector3& v) + { + return ESM::Pathgrid::Point(static_cast(v[0]), static_cast(v[1]), static_cast(v[2])); + } + + /// utility function to convert an ESM::Position to a Pathgrid::Point + static ESM::Pathgrid::Point MakePathgridPoint(const ESM::Position& p) + { + return ESM::Pathgrid::Point(static_cast(p.pos[0]), static_cast(p.pos[1]), static_cast(p.pos[2])); + } + + /// utility function to convert a Pathgrid::Point to a Ogre::Vector3 + static Ogre::Vector3 MakeOgreVector3(const ESM::Pathgrid::Point& p) + { + return Ogre::Vector3(static_cast(p.mX), static_cast(p.mY), static_cast(p.mZ)); + } + private: bool mIsPathConstructed; diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index 9e50af2b8c..c1e094bb1e 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -27,7 +27,7 @@ namespace // float manhattan(const ESM::Pathgrid::Point& a, const ESM::Pathgrid::Point& b) { - return 300 * (abs(a.mX - b.mX) + abs(a.mY - b.mY) + abs(a.mZ - b.mZ)); + return 300.0f * (abs(a.mX - b.mX) + abs(a.mY - b.mY) + abs(a.mZ - b.mZ)); } // Choose a heuristics - Note that these may not be the best for directed @@ -317,23 +317,23 @@ namespace MWMechanics float yCell = 0; if (mIsExterior) { - xCell = mPathgrid->mData.mX * ESM::Land::REAL_SIZE; - yCell = mPathgrid->mData.mY * ESM::Land::REAL_SIZE; + xCell = static_cast(mPathgrid->mData.mX * ESM::Land::REAL_SIZE); + yCell = static_cast(mPathgrid->mData.mY * ESM::Land::REAL_SIZE); } while(graphParent[current] != -1) { ESM::Pathgrid::Point pt = mPathgrid->mPoints[current]; - pt.mX += xCell; - pt.mY += yCell; + pt.mX += static_cast(xCell); + pt.mY += static_cast(yCell); path.push_front(pt); current = graphParent[current]; } // add first node to path explicitly ESM::Pathgrid::Point pt = mPathgrid->mPoints[start]; - pt.mX += xCell; - pt.mY += yCell; + pt.mX += static_cast(xCell); + pt.mY += static_cast(yCell); path.push_front(pt); return path; } diff --git a/apps/openmw/mwmechanics/pathgrid.hpp b/apps/openmw/mwmechanics/pathgrid.hpp index 2742957a68..67fbacdeda 100644 --- a/apps/openmw/mwmechanics/pathgrid.hpp +++ b/apps/openmw/mwmechanics/pathgrid.hpp @@ -6,7 +6,7 @@ namespace ESM { - class Cell; + struct Cell; } namespace MWWorld diff --git a/apps/openmw/mwmechanics/pickpocket.cpp b/apps/openmw/mwmechanics/pickpocket.cpp index 14abcd643e..561011df38 100644 --- a/apps/openmw/mwmechanics/pickpocket.cpp +++ b/apps/openmw/mwmechanics/pickpocket.cpp @@ -1,5 +1,7 @@ #include "pickpocket.hpp" +#include + #include "../mwworld/class.hpp" #include "../mwworld/esmstore.hpp" @@ -20,10 +22,10 @@ namespace MWMechanics float Pickpocket::getChanceModifier(const MWWorld::Ptr &ptr, float add) { NpcStats& stats = ptr.getClass().getNpcStats(ptr); - float agility = stats.getAttribute(ESM::Attribute::Agility).getModified(); - float luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); - float sneak = ptr.getClass().getSkill(ptr, ESM::Skill::Sneak); - return (add + 0.2 * agility + 0.1 * luck + sneak) * stats.getFatigueTerm(); + float agility = static_cast(stats.getAttribute(ESM::Attribute::Agility).getModified()); + float luck = static_cast(stats.getAttribute(ESM::Attribute::Luck).getModified()); + float sneak = static_cast(ptr.getClass().getSkill(ptr, ESM::Skill::Sneak)); + return (add + 0.2f * agility + 0.1f * luck + sneak) * stats.getFatigueTerm(); } bool Pickpocket::getDetected(float valueTerm) @@ -33,13 +35,13 @@ namespace MWMechanics float t = 2*x - y; - float pcSneak = mThief.getClass().getSkill(mThief, ESM::Skill::Sneak); + float pcSneak = static_cast(mThief.getClass().getSkill(mThief, ESM::Skill::Sneak)); int iPickMinChance = MWBase::Environment::get().getWorld()->getStore().get() .find("iPickMinChance")->getInt(); int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get() .find("iPickMaxChance")->getInt(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] + int roll = OEngine::Misc::Rng::roll0to99(); if (t < pcSneak / iPickMinChance) { return (roll > int(pcSneak / iPickMinChance)); @@ -53,7 +55,7 @@ namespace MWMechanics bool Pickpocket::pick(MWWorld::Ptr item, int count) { - float stackValue = item.getClass().getValue(item) * count; + float stackValue = static_cast(item.getClass().getValue(item) * count); float fPickPocketMod = MWBase::Environment::get().getWorld()->getStore().get() .find("fPickPocketMod")->getFloat(); float valueTerm = 10 * fPickPocketMod * stackValue; diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp index 6d6f889edc..b5058fb88e 100644 --- a/apps/openmw/mwmechanics/repair.cpp +++ b/apps/openmw/mwmechanics/repair.cpp @@ -2,6 +2,8 @@ #include +#include + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -44,12 +46,12 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) float toolQuality = ref->mBase->mData.mQuality; - float x = (0.1 * pcStrength + 0.1 * pcLuck + armorerSkill) * fatigueTerm; + float x = (0.1f * pcStrength + 0.1f * pcLuck + armorerSkill) * fatigueTerm; - int roll = static_cast (std::rand()) / RAND_MAX * 100; + int roll = OEngine::Misc::Rng::roll0to99(); if (roll <= x) { - int y = fRepairAmountMult * toolQuality * roll; + int y = static_cast(fRepairAmountMult * toolQuality * roll); y = std::max(1, y); // repair by 'y' points diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 4a049d60f8..3f72f1b669 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -1,5 +1,7 @@ #include "security.hpp" +#include + #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/esmstore.hpp" @@ -20,9 +22,9 @@ namespace MWMechanics { CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); NpcStats& npcStats = actor.getClass().getNpcStats(actor); - mAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified(); - mLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified(); - mSecuritySkill = npcStats.getSkill(ESM::Skill::Security).getModified(); + mAgility = static_cast(creatureStats.getAttribute(ESM::Attribute::Agility).getModified()); + mLuck = static_cast(creatureStats.getAttribute(ESM::Attribute::Luck).getModified()); + mSecuritySkill = static_cast(npcStats.getSkill(ESM::Skill::Security).getModified()); mFatigueTerm = creatureStats.getFatigueTerm(); } @@ -38,7 +40,7 @@ namespace MWMechanics float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get().find("fPickLockMult")->getFloat(); - float x = 0.2 * mAgility + 0.1 * mLuck + mSecuritySkill; + float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill; x *= pickQuality * mFatigueTerm; x += fPickLockMult * lockStrength; @@ -48,8 +50,7 @@ namespace MWMechanics else { MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, lock); - int roll = static_cast (std::rand()) / RAND_MAX * 100; - if (roll <= x) + if (OEngine::Misc::Rng::roll0to99() <= x) { lock.getClass().unlock(lock); resultMessage = "#{sLockSuccess}"; @@ -76,11 +77,11 @@ namespace MWMechanics float probeQuality = probe.get()->mBase->mData.mQuality; const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get().find(trap.getCellRef().getTrap()); - float trapSpellPoints = trapSpell->mData.mCost; + int trapSpellPoints = trapSpell->mData.mCost; float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get().find("fTrapCostMult")->getFloat(); - float x = 0.2 * mAgility + 0.1 * mLuck + mSecuritySkill; + float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill; x += fTrapCostMult * trapSpellPoints; x *= probeQuality * mFatigueTerm; @@ -90,8 +91,7 @@ namespace MWMechanics else { MWBase::Environment::get().getMechanicsManager()->objectOpened(mActor, trap); - int roll = static_cast (std::rand()) / RAND_MAX * 100; - if (roll <= x) + if (OEngine::Misc::Rng::roll0to99() <= x) { trap.getCellRef().setTrap(""); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 105fa58664..8a43cc9322 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -4,6 +4,8 @@ #include +#include + #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -56,6 +58,64 @@ namespace } } + void applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude) + { + MWMechanics::DynamicStat value = target.getClass().getCreatureStats(target).getDynamic(attribute); + value.setCurrent(value.getCurrent()+magnitude, attribute == 2); + target.getClass().getCreatureStats(target).setDynamic(attribute, value); + } + + // TODO: refactor the effect tick functions in Actors so they can be reused here + void applyInstantEffectTick(MWMechanics::EffectKey effect, const MWWorld::Ptr& target, float magnitude) + { + int effectId = effect.mId; + if (effectId == ESM::MagicEffect::DamageHealth) + { + applyDynamicStatsEffect(0, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreHealth) + { + applyDynamicStatsEffect(0, target, magnitude); + } + else if (effectId == ESM::MagicEffect::DamageFatigue) + { + applyDynamicStatsEffect(2, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreFatigue) + { + applyDynamicStatsEffect(2, target, magnitude); + } + else if (effectId == ESM::MagicEffect::DamageMagicka) + { + applyDynamicStatsEffect(1, target, magnitude * -1); + } + else if (effectId == ESM::MagicEffect::RestoreMagicka) + { + applyDynamicStatsEffect(1, target, magnitude); + } + else if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute) + { + int attribute = effect.mArg; + MWMechanics::AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute); + if (effectId == ESM::MagicEffect::DamageAttribute) + value.damage(magnitude); + else + value.restore(magnitude); + target.getClass().getCreatureStats(target).setAttribute(attribute, value); + } + else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill) + { + if (target.getTypeName() != typeid(ESM::NPC).name()) + return; + int skill = effect.mArg; + MWMechanics::SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill); + if (effectId == ESM::MagicEffect::DamageSkill) + value.damage(magnitude); + else + value.restore(magnitude); + } + } + } namespace MWMechanics @@ -86,21 +146,21 @@ namespace MWMechanics for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) { - float x = it->mDuration; + float x = static_cast(it->mDuration); const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find( it->mEffectID); if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) x = std::max(1.f, x); - x *= 0.1 * magicEffect->mData.mBaseCost; - x *= 0.5 * (it->mMagnMin + it->mMagnMax); - x *= it->mArea * 0.05 * magicEffect->mData.mBaseCost; + x *= 0.1f * magicEffect->mData.mBaseCost; + x *= 0.5f * (it->mMagnMin + it->mMagnMax); + x *= it->mArea * 0.05f * magicEffect->mData.mBaseCost; if (it->mRange == ESM::RT_Target) - x *= 1.5; + x *= 1.5f; static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get().find( "fEffectCostMult")->getFloat(); x *= fEffectCostMult; - float s = 2 * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool)); + float s = 2.0f * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool)); if (s - x < y) { y = s - x; @@ -116,13 +176,13 @@ namespace MWMechanics if (spell->mData.mFlags & ESM::Spell::F_Always) return 100; - int castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude(); + float castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude(); int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified(); - float castChance = (lowestSkill - spell->mData.mCost + castBonus + 0.2 * actorWillpower + 0.1 * actorLuck) * stats.getFatigueTerm(); - if (MWBase::Environment::get().getWorld()->getGodModeState() && actor.getRefData().getHandle() == "player") + float castChance = (lowestSkill - spell->mData.mCost + castBonus + 0.2f * actorWillpower + 0.1f * actorLuck) * stats.getFatigueTerm(); + if (MWBase::Environment::get().getWorld()->getGodModeState() && actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) castChance = 100; if (!cap) @@ -209,9 +269,9 @@ namespace MWMechanics float resistance = getEffectResistanceAttribute(effectId, magicEffects); - float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); - float luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); - float x = (willpower + 0.1 * luck) * stats.getFatigueTerm(); + int willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); + float luck = static_cast(stats.getAttribute(ESM::Attribute::Luck).getModified()); + float x = (willpower + 0.1f * luck) * stats.getFatigueTerm(); // This makes spells that are easy to cast harder to resist and vice versa float castChance = 100.f; @@ -222,7 +282,7 @@ namespace MWMechanics if (castChance > 0) x *= 50 / castChance; - float roll = static_cast(std::rand()) / RAND_MAX * 100; + float roll = OEngine::Misc::Rng::rollClosedProbability() * 100; if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) roll -= resistance; @@ -325,11 +385,10 @@ namespace MWMechanics target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).getMagnitude() : target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).getMagnitude(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (roll <= x) + if (OEngine::Misc::Rng::roll0to99() <= x) { // Fully resisted, show message - if (target.getRefData().getHandle() == "player") + if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicPCResisted}"); return; } @@ -347,7 +406,7 @@ namespace MWMechanics if (target.getClass().isActor()) targetEffects += target.getClass().getCreatureStats(target).getMagicEffects(); - bool castByPlayer = (!caster.isEmpty() && caster.getRefData().getHandle() == "player"); + bool castByPlayer = (!caster.isEmpty() && caster == MWBase::Environment::get().getWorld()->getPlayerPtr()); // Try absorbing if it's a spell // NOTE: Vanilla does this once per effect source instead of adding the % from all sources together, not sure @@ -355,9 +414,8 @@ namespace MWMechanics bool absorbed = false; if (spell && caster != target && target.getClass().isActor()) { - int absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).getMagnitude(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - absorbed = (roll < absorb); + float absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).getMagnitude(); + absorbed = (OEngine::Misc::Rng::roll0to99() < absorb); if (absorbed) { const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_Absorb"); @@ -404,9 +462,8 @@ namespace MWMechanics // Try reflecting if (!reflected && magnitudeMult > 0 && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)) { - int reflect = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::Reflect).getMagnitude(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - bool isReflected = (roll < reflect); + float reflect = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::Reflect).getMagnitude(); + bool isReflected = (OEngine::Misc::Rng::roll0to99() < reflect); if (isReflected) { const ESM::Static* reflectStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_Reflect"); @@ -424,7 +481,7 @@ namespace MWMechanics if (magnitudeMult == 0) { // Fully resisted, show message - if (target.getRefData().getHandle() == "player") + if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicPCResisted}"); else if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}"); @@ -434,17 +491,17 @@ namespace MWMechanics if (magnitudeMult > 0 && !absorbed) { - float random = std::rand() / static_cast(RAND_MAX); + float random = OEngine::Misc::Rng::rollClosedProbability(); float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; magnitude *= magnitudeMult; - bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) && effectIt->mDuration > 0; - if (target.getClass().isActor() && hasDuration) + bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); + if (target.getClass().isActor() && hasDuration && effectIt->mDuration > 0) { ActiveSpells::ActiveEffect effect; effect.mEffectId = effectIt->mEffectID; effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; - effect.mDuration = effectIt->mDuration; + effect.mDuration = static_cast(effectIt->mDuration); effect.mMagnitude = magnitude; targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude)); @@ -471,7 +528,12 @@ namespace MWMechanics } } else - applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); + { + if (hasDuration && target.getClass().isActor()) + applyInstantEffectTick(EffectKey(*effectIt), target, magnitude); + else + applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); + } // Re-casting a summon effect will remove the creature from previous castings of that effect. if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor()) @@ -485,16 +547,6 @@ namespace MWMechanics } } - // HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent. - // This was probably just done to have the effect visible in the magic menu for a while - // to notify the player they've been damaged? - if (effectIt->mEffectID == ESM::MagicEffect::DamageAttribute - || effectIt->mEffectID == ESM::MagicEffect::DamageSkill - || effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute - || effectIt->mEffectID == ESM::MagicEffect::RestoreSkill - ) - applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude); - if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) { // Play sound, only for the first effect @@ -520,7 +572,7 @@ namespace MWMechanics castStatic = MWBase::Environment::get().getWorld()->getStore().get().find ("VFX_DefaultHit"); // TODO: VFX are no longer active after saving/reloading the game - bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; + bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; // Note: in case of non actor, a free effect should be fine as well MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); if (anim) @@ -558,9 +610,9 @@ namespace MWMechanics { if (target.getCellRef().getLockLevel() < magnitude) //If the door is not already locked to a higher value, lock it to spell magnitude { - if (caster.getRefData().getHandle() == "player") + if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicLockSuccess}"); - target.getCellRef().setLockLevel(magnitude); + target.getCellRef().setLockLevel(static_cast(magnitude)); } } else if (effectId == ESM::MagicEffect::Open) @@ -573,7 +625,7 @@ namespace MWMechanics if (!caster.isEmpty() && caster.getClass().isActor()) MWBase::Environment::get().getMechanicsManager()->objectOpened(caster, target); - if (caster.getRefData().getHandle() == "player") + if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicOpenSuccess}"); } target.getCellRef().setLockLevel(-abs(target.getCellRef().getLockLevel())); @@ -584,53 +636,6 @@ namespace MWMechanics } else { - if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute) - { - int attribute = effect.mArg; - AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute); - if (effectId == ESM::MagicEffect::DamageAttribute) - value.damage(magnitude); - else - value.restore(magnitude); - target.getClass().getCreatureStats(target).setAttribute(attribute, value); - } - // TODO: refactor the effect tick functions in Actors so they can be reused here - else if (effectId == ESM::MagicEffect::DamageHealth) - { - applyDynamicStatsEffect(0, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreHealth) - { - applyDynamicStatsEffect(0, target, magnitude); - } - else if (effectId == ESM::MagicEffect::DamageFatigue) - { - applyDynamicStatsEffect(2, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreFatigue) - { - applyDynamicStatsEffect(2, target, magnitude); - } - else if (effectId == ESM::MagicEffect::DamageMagicka) - { - applyDynamicStatsEffect(1, target, magnitude * -1); - } - else if (effectId == ESM::MagicEffect::RestoreMagicka) - { - applyDynamicStatsEffect(1, target, magnitude); - } - else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill) - { - if (target.getTypeName() != typeid(ESM::NPC).name()) - return; - int skill = effect.mArg; - SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill); - if (effectId == ESM::MagicEffect::DamageSkill) - value.damage(magnitude); - else - value.restore(magnitude); - } - if (effectId == ESM::MagicEffect::CurePoison) target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); else if (effectId == ESM::MagicEffect::CureParalyzation) @@ -646,7 +651,7 @@ namespace MWMechanics else if (effectId == ESM::MagicEffect::RemoveCurse) target.getClass().getCreatureStats(target).getSpells().purgeCurses(); - if (target.getRefData().getHandle() != "player") + if (target != MWBase::Environment::get().getWorld()->getPlayerPtr()) return; if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled()) return; @@ -680,13 +685,7 @@ namespace MWMechanics } } } - - void CastSpell::applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude) - { - DynamicStat value = target.getClass().getCreatureStats(target).getDynamic(attribute); - value.setCurrent(value.getCurrent()+magnitude, attribute == 2); - target.getClass().getCreatureStats(target).setDynamic(attribute, value); - } + bool CastSpell::cast(const std::string &id) { @@ -721,14 +720,14 @@ namespace MWMechanics // Check if there's enough charge left if (enchantment->mData.mType == ESM::Enchantment::WhenUsed || enchantment->mData.mType == ESM::Enchantment::WhenStrikes) { - const int castCost = getEffectiveEnchantmentCastCost(enchantment->mData.mCost, mCaster); + const int castCost = getEffectiveEnchantmentCastCost(static_cast(enchantment->mData.mCost), mCaster); if (item.getCellRef().getEnchantmentCharge() == -1) - item.getCellRef().setEnchantmentCharge(enchantment->mData.mCharge); + item.getCellRef().setEnchantmentCharge(static_cast(enchantment->mData.mCharge)); if (item.getCellRef().getEnchantmentCharge() < castCost) { - if (mCaster.getRefData().getHandle() == "player") + if (mCaster == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}"); // Failure sound @@ -752,14 +751,14 @@ namespace MWMechanics if (enchantment->mData.mType == ESM::Enchantment::WhenUsed) { - if (mCaster.getRefData().getHandle() == "player") + if (mCaster == MWBase::Environment::get().getWorld()->getPlayerPtr()) mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 1); } if (enchantment->mData.mType == ESM::Enchantment::CastOnce) item.getContainerStore()->remove(item, 1, mCaster); else if (enchantment->mData.mType != ESM::Enchantment::WhenStrikes) { - if (mCaster.getRefData().getHandle() == "player") + if (mCaster == MWBase::Environment::get().getWorld()->getPlayerPtr()) { mCaster.getClass().skillUsageSucceeded (mCaster, ESM::Skill::Enchant, 3); } @@ -823,11 +822,10 @@ namespace MWMechanics bool fail = false; // Check success - int successChance = getSpellSuccessChance(spell, mCaster); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] - if (!fail && roll >= successChance) + float successChance = getSpellSuccessChance(spell, mCaster); + if (OEngine::Misc::Rng::roll0to99() >= successChance) { - if (mCaster.getRefData().getHandle() == "player") + if (mCaster == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}"); fail = true; } @@ -845,7 +843,7 @@ namespace MWMechanics } } - if (mCaster.getRefData().getHandle() == "player" && spellIncreasesSkill(spell)) + if (mCaster == MWBase::Environment::get().getWorld()->getPlayerPtr() && spellIncreasesSkill(spell)) mCaster.getClass().skillUsageSucceeded(mCaster, spellSchoolToSkill(school), 0); @@ -899,11 +897,11 @@ namespace MWMechanics const MWMechanics::CreatureStats& creatureStats = mCaster.getClass().getCreatureStats(mCaster); float x = (npcStats.getSkill (ESM::Skill::Alchemy).getModified() + - 0.2 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified() - + 0.1 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()) + 0.2f * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified() + + 0.1f * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()) * creatureStats.getFatigueTerm(); - int roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] + int roll = OEngine::Misc::Rng::roll0to99(); if (roll > x) { // "X has no effect on you" @@ -915,24 +913,24 @@ namespace MWMechanics float magnitude = 0; float y = roll / std::min(x, 100.f); - y *= 0.25 * x; + y *= 0.25f * x; if (magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) - effect.mDuration = int(y); + effect.mDuration = static_cast(y); else effect.mDuration = 1; if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) { if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) - magnitude = int((0.05 * y) / (0.1 * magicEffect->mData.mBaseCost)); + magnitude = floor((0.05f * y) / (0.1f * magicEffect->mData.mBaseCost)); else - magnitude = int(y / (0.1 * magicEffect->mData.mBaseCost)); + magnitude = floor(y / (0.1f * magicEffect->mData.mBaseCost)); magnitude = std::max(1.f, magnitude); } else magnitude = 1; - effect.mMagnMax = magnitude; - effect.mMagnMin = magnitude; + effect.mMagnMax = static_cast(magnitude); + effect.mMagnMin = static_cast(magnitude); ESM::EffectList effects; effects.mList.push_back(effect); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index 2d550e0856..f50584edf2 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -17,7 +17,7 @@ namespace ESM namespace MWMechanics { - class EffectKey; + struct EffectKey; class MagicEffects; ESM::Skill::SkillEnum spellSchoolToSkill(int school); @@ -97,8 +97,6 @@ namespace MWMechanics /// @note \a caster can be any type of object, or even an empty object. void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude); - - void applyDynamicStatsEffect (int attribute, const MWWorld::Ptr& target, float magnitude); }; } diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index dcbd3f09f3..04225b43eb 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -38,7 +38,7 @@ namespace MWMechanics for (unsigned int i=0; imEffects.mList.size();++i) { if (spell->mEffects.mList[i].mMagnMin != spell->mEffects.mList[i].mMagnMax) - random[i] = static_cast (std::rand()) / RAND_MAX; + random[i] = OEngine::Misc::Rng::rollClosedProbability(); } } diff --git a/apps/openmw/mwmechanics/stat.cpp b/apps/openmw/mwmechanics/stat.cpp index 61b6d60ad4..1b909d579c 100644 --- a/apps/openmw/mwmechanics/stat.cpp +++ b/apps/openmw/mwmechanics/stat.cpp @@ -15,7 +15,6 @@ void MWMechanics::AttributeValue::readState (const ESM::StatState& state) mDamage = state.mDamage; } - void MWMechanics::SkillValue::writeState (ESM::StatState& state) const { AttributeValue::writeState (state); @@ -26,4 +25,4 @@ void MWMechanics::SkillValue::readState (const ESM::StatState& state) { AttributeValue::readState (state); mProgress = state.mProgress; -} \ No newline at end of file +} diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 1c33db0fd2..ffbc19e151 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -170,10 +170,10 @@ namespace MWMechanics } /// Change modified relatively. - void modify (const T& diff) + void modify (const T& diff, bool allowCurrentDecreaseBelowZero=false) { mStatic.modify (diff); - setCurrent (getCurrent()+diff); + setCurrent (getCurrent()+diff, allowCurrentDecreaseBelowZero); } void setCurrent (const T& value, bool allowDecreaseBelowZero = false) @@ -198,11 +198,11 @@ namespace MWMechanics } } - void setModifier (const T& modifier) + void setModifier (const T& modifier, bool allowCurrentDecreaseBelowZero=false) { T diff = modifier - mStatic.getModifier(); mStatic.setModifier (modifier); - setCurrent (getCurrent()+diff); + setCurrent (getCurrent()+diff, allowCurrentDecreaseBelowZero); } void writeState (ESM::StatState& state) const @@ -246,11 +246,16 @@ namespace MWMechanics int getModifier() const { return mModifier; } void setBase(int base) { mBase = std::max(0, base); } + void setModifier(int mod) { mModifier = mod; } - void damage(float damage) { mDamage += damage; } + // Maximum attribute damage is limited to the modified value. + // Note: I think MW applies damage directly to mModified, since you can also + // "restore" drained attributes. We need to rewrite the magic effect system to support this. + void damage(float damage) { mDamage += std::min(damage, (float)getModified()); } void restore(float amount) { mDamage -= std::min(mDamage, amount); } - int getDamage() const { return mDamage; } + + float getDamage() const { return mDamage; } void writeState (ESM::StatState& state) const; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 50afc5afdd..871561bdcf 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -365,7 +365,7 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScene // with the standard 1 / (c + d*l + d*d*q) equation the attenuation factor never becomes zero, // so we ignore lights if their attenuation falls below this factor. - const float threshold = 0.03; + const float threshold = 0.03f; float quadraticAttenuation = 0; float linearAttenuation = 0; @@ -1271,7 +1271,11 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con if (bonename.empty()) params.mObjects = NifOgre::Loader::createObjects(mInsert, model); else + { + if (!mSkelBase) + return; params.mObjects = NifOgre::Loader::createObjects(mSkelBase, bonename, "", mInsert, model); + } setRenderProperties(params.mObjects, RV_Effects, RQG_Main, RQG_Alpha, 0.f, false, NULL); @@ -1473,7 +1477,7 @@ void Animation::setLightEffect(float effect) } mGlowLight->setType(Ogre::Light::LT_POINT); effect += 3; - mGlowLight->setAttenuation(1.0f / (0.03 * (0.5/effect)), 0, 0.5/effect, 0); + mGlowLight->setAttenuation(1.0f / (0.03f * (0.5f/effect)), 0, 0.5f/effect, 0); } } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 756c79ad83..8071dd5fda 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -69,13 +69,13 @@ namespace MWRender /// \todo Read the fallback values from INIImporter (Inventory:Directional*) l = mSceneMgr->createLight(); l->setType (Ogre::Light::LT_DIRECTIONAL); - l->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + l->setDirection (Ogre::Vector3(0.3f, -0.7f, 0.3f)); l->setDiffuseColour (Ogre::ColourValue(1,1,1)); mSceneMgr->setAmbientLight (Ogre::ColourValue(0.25, 0.25, 0.25)); mCamera = mSceneMgr->createCamera (mName); - mCamera->setFOVy(Ogre::Degree(12.3)); + mCamera->setFOVy(Ogre::Degree(12.3f)); mCamera->setAspectRatio (float(mSizeX) / float(mSizeY)); Ogre::SceneNode* renderRoot = mSceneMgr->getRootSceneNode()->createChildSceneNode("renderRoot"); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 2bdf8a499a..7260fc6d15 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -88,6 +88,9 @@ void CreatureWeaponAnimation::updateParts() void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slot) { + if (!mSkelBase) + return; + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); MWWorld::ContainerStoreIterator it = inv.getSlot(slot); @@ -181,7 +184,9 @@ void CreatureWeaponAnimation::releaseArrow() Ogre::Vector3 CreatureWeaponAnimation::runAnimation(float duration) { Ogre::Vector3 ret = Animation::runAnimation(duration); - pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton()); + + if (mSkelBase) + pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton()); if (!mWeapon.isNull()) { diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 972c1b6dd0..79eeff2d04 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -21,6 +21,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/esmstore.hpp" +#include "../mwmechanics/pathfinding.hpp" #include "renderconst.hpp" @@ -81,12 +82,12 @@ ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid) { const ESM::Pathgrid::Edge &edge = *it; const ESM::Pathgrid::Point &p1 = pathgrid->mPoints[edge.mV0], &p2 = pathgrid->mPoints[edge.mV1]; - Vector3 direction = (Vector3(p2.mX, p2.mY, p2.mZ) - Vector3(p1.mX, p1.mY, p1.mZ)); + Vector3 direction = (MWMechanics::PathFinder::MakeOgreVector3(p2) - MWMechanics::PathFinder::MakeOgreVector3(p1)); Vector3 lineDisplacement = direction.crossProduct(Vector3::UNIT_Z).normalisedCopy(); lineDisplacement = lineDisplacement * POINT_MESH_BASE + Vector3(0, 0, 10); // move lines up a little, so they will be less covered by meshes/landscape - result->position(Vector3(p1.mX, p1.mY, p1.mZ) + lineDisplacement); - result->position(Vector3(p2.mX, p2.mY, p2.mZ) + lineDisplacement); + result->position(MWMechanics::PathFinder::MakeOgreVector3(p1) + lineDisplacement); + result->position(MWMechanics::PathFinder::MakeOgreVector3(p2) + lineDisplacement); } result->end(); @@ -108,7 +109,7 @@ ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid) it != pathgrid->mPoints.end(); ++it, startIndex += 6) { - Vector3 pointPos(it->mX, it->mY, it->mZ); + Vector3 pointPos(MWMechanics::PathFinder::MakeOgreVector3(*it)); if (!first) { @@ -117,11 +118,13 @@ ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid) result->index(startIndex); // start point of current octahedron } + Ogre::Real pointMeshBase = static_cast(POINT_MESH_BASE); + result->position(pointPos + Vector3(0, 0, height)); // 0 - result->position(pointPos + Vector3(-POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 1 - result->position(pointPos + Vector3(POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 2 - result->position(pointPos + Vector3(POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 3 - result->position(pointPos + Vector3(-POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 4 + result->position(pointPos + Vector3(-pointMeshBase, -pointMeshBase, 0)); // 1 + result->position(pointPos + Vector3(pointMeshBase, -pointMeshBase, 0)); // 2 + result->position(pointPos + Vector3(pointMeshBase, pointMeshBase, 0)); // 3 + result->position(pointPos + Vector3(-pointMeshBase, pointMeshBase, 0)); // 4 result->position(pointPos + Vector3(0, 0, -height)); // 5 result->index(startIndex + 0); @@ -239,8 +242,8 @@ void Debugging::enableCellPathgrid(MWWorld::CellStore *store) Vector3 cellPathGridPos(0, 0, 0); if (store->getCell()->isExterior()) { - cellPathGridPos.x = store->getCell()->mData.mX * ESM::Land::REAL_SIZE; - cellPathGridPos.y = store->getCell()->mData.mY * ESM::Land::REAL_SIZE; + cellPathGridPos.x = static_cast(store->getCell()->mData.mX * ESM::Land::REAL_SIZE); + cellPathGridPos.y = static_cast(store->getCell()->mData.mY * ESM::Land::REAL_SIZE); } SceneNode *cellPathGrid = mPathGridRoot->createChildSceneNode(cellPathGridPos); cellPathGrid->attachObject(createPathgridLines(pathgrid)); diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index de78748b57..95d4429d6f 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -86,8 +86,8 @@ namespace MWRender { for (int cellX=0; cellX(float(cellX)/float(mCellSize) * 9); + int vertexY = static_cast(float(cellY) / float(mCellSize) * 9); int texelX = (x-mMinX) * mCellSize + cellX; @@ -102,9 +102,9 @@ namespace MWRender y = (SCHAR_MIN << 4) / 2048.f; if (y < 0) { - r = (14 * y + 38); - g = 20 * y + 56; - b = 18 * y + 51; + r = static_cast(14 * y + 38); + g = static_cast(20 * y + 56); + b = static_cast(18 * y + 51); } else if (y < 0.3f) { @@ -112,20 +112,20 @@ namespace MWRender y *= 8.f; else { - y -= 0.1; - y += 0.8; + y -= 0.1f; + y += 0.8f; } - r = 66 - 32 * y; - g = 48 - 23 * y; - b = 33 - 16 * y; + r = static_cast(66 - 32 * y); + g = static_cast(48 - 23 * y); + b = static_cast(33 - 16 * y); } else { y -= 0.3f; y *= 1.428f; - r = 34 - 29 * y; - g = 25 - 20 * y; - b = 17 - 12 * y; + r = static_cast(34 - 29 * y); + g = static_cast(25 - 20 * y); + b = static_cast(17 - 12 * y); } data[texelY * mWidth * 3 + texelX * 3] = r; @@ -172,9 +172,9 @@ namespace MWRender void GlobalMap::exploreCell(int cellX, int cellY) { - float originX = (cellX - mMinX) * mCellSize; + float originX = static_cast((cellX - mMinX) * mCellSize); // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is - float originY = mHeight - (cellY+1 - mMinY) * mCellSize; + float originY = static_cast(mHeight - (cellY + 1 - mMinY) * mCellSize); if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; @@ -188,7 +188,8 @@ namespace MWRender int mapHeight = localMapTexture->getHeight(); mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,mapWidth,mapHeight), - Ogre::Image::Box(originX,originY,originX+mCellSize,originY+mCellSize)); + Ogre::Image::Box(static_cast(originX), static_cast(originY), + static_cast(originX + mCellSize), static_cast(originY + mCellSize))); Ogre::Image backup; std::vector data; @@ -204,7 +205,7 @@ namespace MWRender assert (originY+y < mOverlayImage.getHeight()); assert (x < int(backup.getWidth())); assert (y < int(backup.getHeight())); - mOverlayImage.setColourAt(backup.getColourAt(x, y, 0), originX+x, originY+y, 0); + mOverlayImage.setColourAt(backup.getColourAt(x, y, 0), static_cast(originX + x), static_cast(originY + y), 0); } } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index b3ae85b115..a162ab68fb 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -12,7 +12,7 @@ namespace Loading namespace ESM { - class GlobalMap; + struct GlobalMap; } namespace MWRender diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 638a086239..0299dc493c 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -43,9 +43,9 @@ LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManag mLight = mRendering->getScene()->createLight(); mLight->setType (Ogre::Light::LT_DIRECTIONAL); - mLight->setDirection (Ogre::Vector3(0.3, 0.3, -0.7)); + mLight->setDirection (Ogre::Vector3(0.3f, 0.3f, -0.7f)); mLight->setVisible (false); - mLight->setDiffuseColour (ColourValue(0.7,0.7,0.7)); + mLight->setDiffuseColour (ColourValue(0.7f,0.7f,0.7f)); mRenderTexture = TextureManager::getSingleton().createManual( "localmap/rtt", @@ -114,8 +114,8 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().y); Vector2 length = max-min; - const int segsX = std::ceil( length.x / sSize ); - const int segsY = std::ceil( length.y / sSize ); + const int segsX = static_cast(std::ceil(length.x / sSize)); + const int segsY = static_cast(std::ceil(length.y / sSize)); mInteriorName = cell->getCell()->mName; @@ -175,7 +175,7 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax) // Note: using force=true for exterior cell maps. // They must be updated even if they were visited before, because the set of surrounding active cells might be different // (and objects in a different cell can "bleed" into another cell's map if they cross the border) - render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name, true); + render((x+0.5f)*sSize, (y+0.5f)*sSize, zMin, zMax, static_cast(sSize), static_cast(sSize), name, true); if (mBuffers.find(name) == mBuffers.end()) { @@ -226,7 +226,7 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, // Do NOT change padding! This will break older savegames. // If the padding really needs to be changed, then it must be saved in the ESM::FogState and // assume the old (500) value as default for older savegames. - const int padding = 500; + const Ogre::Real padding = 500.0f; // Apply a little padding mBounds.setMinimum (mBounds.getMinimum() - Vector3(padding,padding,0)); @@ -279,8 +279,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, mCameraPosNode->setPosition(Vector3(center.x, center.y, 0)); // divide into segments - const int segsX = std::ceil( length.x / sSize ); - const int segsY = std::ceil( length.y / sSize ); + const int segsX = static_cast(std::ceil(length.x / sSize)); + const int segsY = static_cast(std::ceil(length.y / sSize)); mInteriorName = cell->getCell()->mName; @@ -289,12 +289,12 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, { for (int y=0; y(sSize*x), static_cast(sSize*y)); Vector2 newcenter = start + sSize/2; std::string texturePrefix = cell->getCell()->mName + "_" + coordStr(x,y); - render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, sSize, sSize, texturePrefix); + render(newcenter.x - center.x, newcenter.y - center.y, zMin, zMax, static_cast(sSize), static_cast(sSize), texturePrefix); if (!cell->getFog()) createFogOfWar(texturePrefix); @@ -397,7 +397,7 @@ void LocalMap::render(const float x, const float y, // set up lighting Ogre::ColourValue oldAmbient = mRendering->getScene()->getAmbientLight(); - mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); + mRendering->getScene()->setAmbientLight(Ogre::ColourValue(0.3f, 0.3f, 0.3f)); mRenderingManager->disableLights(true); mLight->setVisible(true); @@ -439,11 +439,11 @@ void LocalMap::worldToInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y); - x = std::ceil((pos.x - min.x)/sSize)-1; - y = std::ceil((pos.y - min.y)/sSize)-1; + x = static_cast(std::ceil((pos.x - min.x) / sSize) - 1); + y = static_cast(std::ceil((pos.y - min.y) / sSize) - 1); nX = (pos.x - min.x - sSize*x)/sSize; - nY = 1.0-(pos.y - min.y - sSize*y)/sSize; + nY = 1.0f-(pos.y - min.y - sSize*y)/sSize; } Ogre::Vector2 LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, int y) @@ -452,7 +452,7 @@ Ogre::Vector2 LocalMap::interiorMapToWorldPosition (float nX, float nY, int x, i Ogre::Vector2 pos; pos.x = sSize * (nX + x) + min.x; - pos.y = sSize * (1.0-nY + y) + min.y; + pos.y = sSize * (1.0f-nY + y) + min.y; pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().y), -mAngle); return pos; @@ -468,8 +468,8 @@ bool LocalMap::isPositionExplored (float nX, float nY, int x, int y, bool interi nX = std::max(0.f, std::min(1.f, nX)); nY = std::max(0.f, std::min(1.f, nY)); - int texU = (sFogOfWarResolution-1) * nX; - int texV = (sFogOfWarResolution-1) * nY; + int texU = static_cast((sFogOfWarResolution - 1) * nX); + int texV = static_cast((sFogOfWarResolution - 1) * nY); Ogre::uint32 clr = mBuffers[texName][texV * sFogOfWarResolution + texU]; uint8 alpha = (clr >> 24); @@ -522,8 +522,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni if (!mInterior) { - x = std::ceil(pos.x / sSize)-1; - y = std::ceil(pos.y / sSize)-1; + x = static_cast(std::ceil(pos.x / sSize) - 1); + y = static_cast(std::ceil(pos.y / sSize) - 1); } else MWBase::Environment::get().getWindowManager()->setActiveMap(x,y,mInterior); @@ -533,7 +533,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni if (!mInterior) { u = std::abs((pos.x - (sSize*x))/sSize); - v = 1.0-std::abs((pos.y - (sSize*y))/sSize); + v = 1.0f-std::abs((pos.y - (sSize*y))/sSize); texBaseName = "Cell_"; } else @@ -545,7 +545,7 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y); // explore radius (squared) - const float exploreRadius = (mInterior ? 0.1 : 0.3) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1 + const float exploreRadius = (mInterior ? 0.1f : 0.3f) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1 const float sqrExploreRadius = Math::Sqr(exploreRadius); const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 7cfa388146..014c67f164 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -14,7 +14,7 @@ namespace MWWorld namespace ESM { - class FogTexture; + struct FogTexture; } namespace MWRender diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 0926498c0a..a724644a70 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -12,6 +12,8 @@ #include +#include + #include #include "../mwworld/esmstore.hpp" @@ -101,7 +103,7 @@ void HeadAnimationTime::setEnabled(bool enabled) void HeadAnimationTime::resetBlinkTimer() { - mBlinkTimer = -(2 + (std::rand() / double(RAND_MAX*1.0)) * 6); + mBlinkTimer = -(2.0f + OEngine::Misc::Rng::rollDice(6)); } void HeadAnimationTime::update(float dt) @@ -335,7 +337,10 @@ void NpcAnimation::updateNpcBase() } void NpcAnimation::updateParts() -{ +{ + if (!mSkelBase) + return; + mAlpha = 1.f; const MWWorld::Class &cls = mPtr.getClass(); @@ -374,7 +379,7 @@ void NpcAnimation::updateParts() }; static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); - bool wasArrowAttached = (mAmmunition.get()); + bool wasArrowAttached = (mAmmunition.get() != NULL); MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) @@ -621,30 +626,33 @@ NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model } Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) -{ +{ Ogre::Vector3 ret = Animation::runAnimation(timepassed); mHeadAnimationTime->update(timepassed); - Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - if(mViewMode == VM_FirstPerson) + if (mSkelBase) { - float pitch = mPtr.getRefData().getPosition().rot[0]; - Ogre::Node *node = baseinst->getBone("Bip01 Neck"); - node->pitch(Ogre::Radian(-pitch), Ogre::Node::TS_WORLD); + Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); + if(mViewMode == VM_FirstPerson) + { + float pitch = mPtr.getRefData().getPosition().rot[0]; + Ogre::Node *node = baseinst->getBone("Bip01 Neck"); + node->pitch(Ogre::Radian(-pitch), Ogre::Node::TS_WORLD); - // This has to be done before this function ends; - // updateSkeletonInstance, below, touches the hands. - node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); - } - else - { - // In third person mode we may still need pitch for ranged weapon targeting - pitchSkeleton(mPtr.getRefData().getPosition().rot[0], baseinst); + // This has to be done before this function ends; + // updateSkeletonInstance, below, touches the hands. + node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); + } + else + { + // In third person mode we may still need pitch for ranged weapon targeting + pitchSkeleton(mPtr.getRefData().getPosition().rot[0], baseinst); - Ogre::Node* node = baseinst->getBone("Bip01 Head"); - if (node) - node->rotate(Ogre::Quaternion(mHeadYaw, Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(mHeadPitch, Ogre::Vector3::UNIT_X), Ogre::Node::TS_WORLD); + Ogre::Node* node = baseinst->getBone("Bip01 Head"); + if (node) + node->rotate(Ogre::Quaternion(mHeadYaw, Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(mHeadPitch, Ogre::Vector3::UNIT_X), Ogre::Node::TS_WORLD); + } } mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. @@ -659,7 +667,9 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) if (!isSkinned(mObjectParts[i])) continue; - updateSkeletonInstance(baseinst, mObjectParts[i]->mSkelBase->getSkeleton()); + if (mSkelBase) + updateSkeletonInstance(mSkelBase->getSkeleton(), mObjectParts[i]->mSkelBase->getSkeleton()); + mObjectParts[i]->mSkelBase->getAllAnimationStates()->_notifyDirty(); } @@ -933,7 +943,7 @@ void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, boo if (!magicEffect->mHit.empty()) { const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get().find (magicEffect->mHit); - bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; + bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; // Don't play particle VFX unless the effect is new or it should be looping. if (isNew || loop) addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, ""); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 9650830191..bdaa2d5157 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -111,7 +111,7 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); mStaticGeometrySmall[ptr.getCell()] = sg; - sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); + sg->setRenderingDistance(static_cast(Settings::Manager::getInt("small object distance", "Viewing distance"))); } else sg = mStaticGeometrySmall[ptr.getCell()]; diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 6cc49089ae..739ed24d9f 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -35,7 +35,7 @@ namespace MWRender vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Refraction); vp->setMaterialScheme("water_refraction"); - vp->setBackgroundColour (Ogre::ColourValue(0.090195, 0.115685, 0.12745)); + vp->setBackgroundColour (Ogre::ColourValue(0.090195f, 0.115685f, 0.12745f)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 05b43d54f5..8fb1ee53c5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -148,8 +148,8 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(0.0))); sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(0))); - sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); - sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); + sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5f, -0.8f, 0.2f))); + sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6f))); sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false"); sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (new sh::Vector4(0,0,0,0))); @@ -321,7 +321,7 @@ void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr) void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) { NpcAnimation *anim = NULL; - if(ptr.getRefData().getHandle() == "player") + if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) anim = mPlayerAnimation; else if(ptr.getClass().isActor()) anim = dynamic_cast(mActors->getAnimation(ptr)); @@ -346,7 +346,7 @@ void RenderingManager::update (float duration, bool paused) MWWorld::Ptr player = world->getPlayerPtr(); - int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); + int blind = static_cast(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude()); MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind))); setAmbientMode(); @@ -365,7 +365,7 @@ void RenderingManager::update (float duration, bool paused) btVector3 btOrig(orig.x, orig.y, orig.z); btVector3 btDest(dest.x, dest.y, dest.z); - std::pair test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest); + std::pair test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5f, btOrig, btDest); if(test.first) mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } @@ -375,8 +375,8 @@ void RenderingManager::update (float duration, bool paused) bool isInAir = !world->isOnGround(player); bool isSwimming = world->isSwimming(player); - static const int i1stPersonSneakDelta = MWBase::Environment::get().getWorld()->getStore().get() - .find("i1stPersonSneakDelta")->getInt(); + static const float i1stPersonSneakDelta = MWBase::Environment::get().getWorld()->getStore().get() + .find("i1stPersonSneakDelta")->getFloat(); if(!paused && isSneaking && !(isSwimming || isInAir)) mCamera->setSneakOffset(i1stPersonSneakDelta); @@ -538,7 +538,7 @@ void RenderingManager::applyFog (bool underwater) } else { - Ogre::ColourValue clv(0.090195, 0.115685, 0.12745); + Ogre::ColourValue clv(0.090195f, 0.115685f, 0.12745f); mRendering.getScene()->setFog (FOG_LINEAR, Ogre::ColourValue(clv), 0, 0, 1000); mRendering.getViewport()->setBackgroundColour (Ogre::ColourValue(clv)); mWater->setViewportBackground (Ogre::ColourValue(clv)); @@ -598,9 +598,9 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour) mAmbientColor = colour; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - int nightEye = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude(); + int nightEye = static_cast(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude()); Ogre::ColourValue final = colour; - final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f)); + final += Ogre::ColourValue(0.7f,0.7f,0.7f,0) * std::min(1.f, (nightEye/100.f)); mRendering.getScene()->setAmbientLight(final); } @@ -662,7 +662,7 @@ void RenderingManager::requestMap(MWWorld::CellStore* cell) assert(mTerrain); Ogre::AxisAlignedBox dims = mObjects->getDimensions(cell); - Ogre::Vector2 center (cell->getCell()->getGridX() + 0.5, cell->getCell()->getGridY() + 0.5); + Ogre::Vector2 center (cell->getCell()->getGridX() + 0.5f, cell->getCell()->getGridY() + 0.5f); dims.merge(mTerrain->getWorldBoundingBox(center)); mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z); @@ -714,8 +714,8 @@ Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds) // make 2D relative/normalized coords from the view-space vertex // by dividing out the Z (depth) factor -- this is an approximation - float x = corner.x / corner.z + 0.5; - float y = corner.y / corner.z + 0.5; + float x = corner.x / corner.z + 0.5f; + float y = corner.y / corner.z + 0.5f; if (x < min_x) min_x = x; @@ -955,7 +955,7 @@ Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr) { Animation *anim = mActors->getAnimation(ptr); - if(!anim && ptr.getRefData().getHandle() == "player") + if(!anim && ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) anim = mPlayerAnimation; if (!anim) diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index bb1bccc0a3..f75061af49 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -107,7 +107,7 @@ void RippleSimulation::update(float dt, Ogre::Vector2 position) Ogre::Radian& rotation = created->rotation; #endif timeToLive = totalTimeToLive = mRippleLifeTime; - colour = Ogre::ColourValue(0.f, 0.f, 0.f, 0.7); // Water_RippleAlphas.x? + colour = Ogre::ColourValue(0.f, 0.f, 0.f, 0.7f); // Water_RippleAlphas.x? direction = Ogre::Vector3(0,0,0); position = currentPos; position.z = 0; // Z is set by the Scene Node diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index 5a6ccaca62..f2e60b11b0 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -21,7 +21,7 @@ using namespace MWRender; Shadows::Shadows(OEngine::Render::OgreRenderer* rend) : mRendering(rend), mSceneMgr(rend->getScene()), mPSSMSetup(NULL), - mShadowFar(1000), mFadeStart(0.9) + mShadowFar(1000), mFadeStart(0.9f) { recreate(); } @@ -58,7 +58,7 @@ void Shadows::recreate() mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R); mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000); - mShadowFar = split ? Settings::Manager::getInt("split shadow distance", "Shadows") : Settings::Manager::getInt("shadow distance", "Shadows"); + mShadowFar = Settings::Manager::getFloat(split ? "split shadow distance" : "shadow distance", "Shadows"); mSceneMgr->setShadowFarDistance(mShadowFar); mFadeStart = Settings::Manager::getFloat("fade start", "Shadows"); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index f6287de5ef..d591cca2ea 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -19,6 +19,8 @@ #include +#include + #include #include @@ -310,22 +312,22 @@ void SkyManager::create() // Create light used for thunderstorm mLightning = mSceneMgr->createLight(); mLightning->setType (Ogre::Light::LT_DIRECTIONAL); - mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + mLightning->setDirection (Ogre::Vector3(0.3f, -0.7f, 0.3f)); mLightning->setVisible (false); mLightning->setDiffuseColour (ColourValue(3,3,3)); const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback(); - mSecunda = new Moon("secunda_texture", fallback->getFallbackFloat("Moons_Secunda_Size")/100, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon"); + mSecunda = new Moon("secunda_texture", fallback->getFallbackFloat("Moons_Secunda_Size")/100, Vector3(-0.4f, 0.4f, 0.5f), mRootNode, "openmw_moon"); mSecunda->setType(Moon::Type_Secunda); mSecunda->setRenderQueue(RQG_SkiesEarly+4); - mMasser = new Moon("masser_texture", fallback->getFallbackFloat("Moons_Masser_Size")/100, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon"); + mMasser = new Moon("masser_texture", fallback->getFallbackFloat("Moons_Masser_Size")/100, Vector3(-0.4f, 0.4f, 0.5f), mRootNode, "openmw_moon"); mMasser->setRenderQueue(RQG_SkiesEarly+3); mMasser->setType(Moon::Type_Masser); - mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun"); + mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4f, 0.4f, 0.4f), mRootNode, "openmw_sun"); mSun->setRenderQueue(RQG_SkiesEarly+4); - mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun"); + mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4f, 0.4f, 0.4f), mRootNode, "openmw_sun"); mSunGlare->setRenderQueue(RQG_SkiesLate); mSunGlare->setVisibilityFlags(RV_NoReflection); @@ -464,8 +466,8 @@ void SkyManager::updateRain(float dt) // TODO: handle rain settings from Morrowind.ini const float rangeRandom = 100; - float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2); - float yOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2); + float xOffs = OEngine::Misc::Rng::rollProbability() * rangeRandom - (rangeRandom / 2); + float yOffs = OEngine::Misc::Rng::rollProbability() * rangeRandom - (rangeRandom / 2); // Create a separate node to control the offset, since a node with setInheritOrientation(false) will still // consider the orientation of the parent node for its position, just not for its orientation @@ -680,9 +682,9 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) if (mCloudColour != weather.mSunColor) { - ColourValue clr( weather.mSunColor.r*0.7 + weather.mAmbientColor.r*0.7, - weather.mSunColor.g*0.7 + weather.mAmbientColor.g*0.7, - weather.mSunColor.b*0.7 + weather.mAmbientColor.b*0.7); + ColourValue clr( weather.mSunColor.r*0.7f + weather.mAmbientColor.r*0.7f, + weather.mSunColor.g*0.7f + weather.mAmbientColor.g*0.7f, + weather.mSunColor.b*0.7f + weather.mAmbientColor.b*0.7f); sh::Factory::getInstance().setSharedParameter ("cloudColour", sh::makeProperty(new sh::Vector3(clr.r, clr.g, clr.b))); @@ -774,7 +776,7 @@ void SkyManager::setSunDirection(const Vector3& direction, bool is_night) mSunGlare->setPosition(direction); float height = direction.z; - float fade = is_night ? 0.0 : (( height > 0.5) ? 1.0 : height * 2); + float fade = is_night ? 0.0f : (( height > 0.5) ? 1.0f : height * 2); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(fade, height))); } @@ -836,7 +838,7 @@ void SkyManager::setSecundaFade(const float fade) void SkyManager::setHour(double hour) { - mHour = hour; + mHour = static_cast(hour); } void SkyManager::setDate(int day, int month) diff --git a/apps/openmw/mwrender/terrainstorage.cpp b/apps/openmw/mwrender/terrainstorage.cpp index e74b6af124..8ad2ea3213 100644 --- a/apps/openmw/mwrender/terrainstorage.cpp +++ b/apps/openmw/mwrender/terrainstorage.cpp @@ -36,13 +36,13 @@ namespace MWRender for (; it != esmStore.get().extEnd(); ++it) { if (it->getGridX() < minX) - minX = it->getGridX(); + minX = static_cast(it->getGridX()); if (it->getGridX() > maxX) - maxX = it->getGridX(); + maxX = static_cast(it->getGridX()); if (it->getGridY() < minY) - minY = it->getGridY(); + minY = static_cast(it->getGridY()); if (it->getGridY() > maxY) - maxY = it->getGridY(); + maxY = static_cast(it->getGridY()); } // since grid coords are at cell origin, we need to add 1 cell diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 456fc47e97..a16b156ae3 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -210,7 +210,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const MWWorld::Fallb int waterScale = 30; MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, - CELL_SIZE*5*waterScale, CELL_SIZE*5*waterScale, 40, 40, true, 1, 3*waterScale,3*waterScale, Vector3::UNIT_Y); + static_cast(CELL_SIZE*5*waterScale), static_cast(CELL_SIZE*5*waterScale), + 40, 40, true, 1, static_cast(3 * waterScale), static_cast(3 * waterScale), Vector3::UNIT_Y); mWater = mSceneMgr->createEntity("water"); mWater->setVisibilityFlags(RV_Water); @@ -284,7 +285,7 @@ void Water::setActive(bool active) mActive = active; updateVisible(); - sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(active ? 1.0 : 0.0))); + sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(active ? 1.0f : 0.0f))); } Water::~Water() @@ -351,7 +352,7 @@ Water::updateUnderwater(bool underwater) Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY) { - return Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), gridY * CELL_SIZE + (CELL_SIZE / 2), mTop); + return Vector3(static_cast(gridX * CELL_SIZE + (CELL_SIZE / 2)), static_cast(gridY * CELL_SIZE + (CELL_SIZE / 2)), mTop); } void Water::setViewportBackground(const ColourValue& bg) diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 10d0a06ffb..775950431e 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -122,7 +122,7 @@ namespace MWRender { bool mIsUnderwater; bool mActive; bool mToggled; - int mTop; + float mTop; float mWaterTimer; diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index a3f9354874..f0cb8a9677 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -107,7 +107,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i(duration), x, y, z); ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr); std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration @@ -145,7 +145,7 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i(duration), x, y, z); ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr); std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration @@ -177,13 +177,13 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer range = runtime[0].mFloat; + Interpreter::Type_Integer range = static_cast(runtime[0].mFloat); runtime.pop(); - Interpreter::Type_Integer duration = runtime[0].mFloat; + Interpreter::Type_Integer duration = static_cast(runtime[0].mFloat); runtime.pop(); - Interpreter::Type_Integer time = runtime[0].mFloat; + Interpreter::Type_Integer time = static_cast(runtime[0].mFloat); runtime.pop(); std::vector idleList; @@ -466,12 +466,9 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getMechanicsManager()->toggleAI(); - context.report (enabled ? "AI -> On" : "AI -> Off"); + runtime.getContext().report (enabled ? "AI -> On" : "AI -> Off"); } }; diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 86329191e3..70475d8e2f 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -175,7 +175,7 @@ namespace MWScript MWWorld::ActionEquip action (*it); action.execute(ptr); - if (ptr.getRefData().getHandle() == "player" && !ptr.getClass().getScript(ptr).empty()) + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr() && !ptr.getClass().getScript(ptr).empty()) ptr.getRefData().getLocals().setVarByInt(ptr.getClass().getScript(ptr), "onpcequip", 1); } }; diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index fd7fe47371..904e0ee850 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -65,12 +65,9 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context - = static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleCollisionMode(); - context.report (enabled ? "Collision -> On" : "Collision -> Off"); + runtime.getContext().report (enabled ? "Collision -> On" : "Collision -> Off"); } }; diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 92fd51d87d..a6ad2cc11a 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -100,7 +100,7 @@ namespace MWScript mStore.get().begin(); iter != mStore.get().end(); ++iter) { - scripts.push_back (iter->mScript); + scripts.push_back (iter->mId); } // add scripts diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 9f009db98f..9b7aa0514e 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -21,7 +21,7 @@ namespace Loading namespace MWWorld { - struct ESMStore; + class ESMStore; } namespace MWScript diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 435f82de7a..a8c04aa4bc 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -270,15 +270,21 @@ namespace MWScript std::string InterpreterContext::getActionBinding(const std::string& action) const { - std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); + MWBase::InputManager* input = MWBase::Environment::get().getInputManager(); + std::vector actions = input->getActionKeySorting (); for (std::vector::const_iterator it = actions.begin(); it != actions.end(); ++it) { - std::string desc = MWBase::Environment::get().getInputManager()->getActionDescription (*it); + std::string desc = input->getActionDescription (*it); if(desc == "") continue; if(desc == action) - return MWBase::Environment::get().getInputManager()->getActionBindingName (*it); + { + if(input->joystickLastUsed()) + return input->getActionControllerBindingName(*it); + else + return input->getActionKeyBindingName (*it); + } } return "None"; @@ -469,7 +475,7 @@ namespace MWScript for (int i=0; i<3; ++i) diff[i] = pos1[i] - pos2[i]; - return std::sqrt (diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]); + return static_cast(std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2])); } bool InterpreterContext::hasBeenActivated (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 698df62c2a..d3841befdf 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -20,7 +20,7 @@ namespace MWInput namespace MWScript { - struct Locals; + class Locals; class InterpreterContext : public Interpreter::Context { diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 9dbf07fba9..a18d0d5ae5 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -63,7 +63,7 @@ namespace MWScript return mLongs.at (index); case 'f': - return mFloats.at (index); + return static_cast(mFloats.at(index)); default: return 0; } @@ -87,7 +87,7 @@ namespace MWScript mLongs.at (index) = val; break; case 'f': - mFloats.at (index) = val; break; + mFloats.at(index) = static_cast(val); break; } return true; } diff --git a/apps/openmw/mwscript/locals.hpp b/apps/openmw/mwscript/locals.hpp index bd95835ac1..a9fcf317c8 100644 --- a/apps/openmw/mwscript/locals.hpp +++ b/apps/openmw/mwscript/locals.hpp @@ -7,7 +7,7 @@ namespace ESM { - struct Script; + class Script; struct Locals; } diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 52094947ce..29f586a653 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -81,7 +81,7 @@ namespace MWScript std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - bool allowSkipping = runtime[0].mInteger; + bool allowSkipping = runtime[0].mInteger != 0; runtime.pop(); MWBase::Environment::get().getWindowManager()->playVideo (name, allowSkipping); @@ -212,13 +212,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_CollisionDebug); - context.report (enabled ? + runtime.getContext().report (enabled ? "Collision Mesh Rendering -> On" : "Collision Mesh Rendering -> Off"); } }; @@ -230,13 +227,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_BoundingBoxes); - context.report (enabled ? + runtime.getContext().report (enabled ? "Bounding Box Rendering -> On" : "Bounding Box Rendering -> Off"); } }; @@ -247,13 +241,10 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_Wireframe); - context.report (enabled ? + runtime.getContext().report (enabled ? "Wireframe Rendering -> On" : "Wireframe Rendering -> Off"); } }; @@ -263,13 +254,10 @@ namespace MWScript public: virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWBase::World::Render_Pathgrid); - context.report (enabled ? + runtime.getContext().report (enabled ? "Path Grid rendering -> On" : "Path Grid Rendering -> Off"); } }; @@ -312,7 +300,7 @@ namespace MWScript Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); - MWBase::Environment::get().getWindowManager()->fadeScreenTo(alpha, time, false); + MWBase::Environment::get().getWindowManager()->fadeScreenTo(static_cast(alpha), time, false); } }; @@ -386,17 +374,14 @@ namespace MWScript virtual void execute(Interpreter::Runtime &runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - MWBase::World *world = MWBase::Environment::get().getWorld(); if (world->toggleVanityMode(sActivate)) { - context.report(sActivate ? "Vanity Mode -> On" : "Vanity Mode -> Off"); + runtime.getContext().report(sActivate ? "Vanity Mode -> On" : "Vanity Mode -> Off"); sActivate = !sActivate; } else { - context.report("Vanity Mode -> No"); + runtime.getContext().report("Vanity Mode -> No"); } } }; @@ -862,14 +847,11 @@ namespace MWScript void printGlobalVars(Interpreter::Runtime &runtime) { - InterpreterContext& context = - static_cast (runtime.getContext()); - std::stringstream str; str<< "Global variables:"; MWBase::World *world = MWBase::Environment::get().getWorld(); - std::vector names = context.getGlobals(); + std::vector names = runtime.getContext().getGlobals(); for(size_t i = 0;i < names.size();++i) { char type = world->getGlobalVariableType (names[i]); @@ -879,17 +861,17 @@ namespace MWScript { case 's': - str << context.getGlobalShort (names[i]) << " (short)"; + str << runtime.getContext().getGlobalShort (names[i]) << " (short)"; break; case 'l': - str << context.getGlobalLong (names[i]) << " (long)"; + str << runtime.getContext().getGlobalLong (names[i]) << " (long)"; break; case 'f': - str << context.getGlobalFloat (names[i]) << " (float)"; + str << runtime.getContext().getGlobalFloat (names[i]) << " (float)"; break; default: @@ -898,7 +880,7 @@ namespace MWScript } } - context.report (str.str()); + runtime.getContext().report (str.str()); } public: @@ -920,11 +902,9 @@ namespace MWScript public: virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleScripts(); - context.report(enabled ? "Scripts -> On" : "Scripts -> Off"); + runtime.getContext().report(enabled ? "Scripts -> On" : "Scripts -> Off"); } }; @@ -933,11 +913,9 @@ namespace MWScript public: virtual void execute (Interpreter::Runtime& runtime) { - InterpreterContext& context = static_cast (runtime.getContext()); - bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode(); - context.report (enabled ? "God Mode -> On" : "God Mode -> Off"); + runtime.getContext().report (enabled ? "God Mode -> On" : "God Mode -> Off"); } }; diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 6026f6aba2..e4a123b864 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -16,7 +16,7 @@ namespace MWWorld { - struct ESMStore; + class ESMStore; } namespace Compiler diff --git a/apps/openmw/mwscript/skyextensions.cpp b/apps/openmw/mwscript/skyextensions.cpp index 0ccd0ce311..d28d01b638 100644 --- a/apps/openmw/mwscript/skyextensions.cpp +++ b/apps/openmw/mwscript/skyextensions.cpp @@ -25,10 +25,7 @@ namespace MWScript { bool enabled = MWBase::Environment::get().getWorld()->toggleSky(); - InterpreterContext& context = - static_cast (runtime.getContext()); - - context.report (enabled ? "Sky -> On" : "Sky -> Off"); + runtime.getContext().report (enabled ? "Sky -> On" : "Sky -> Off"); } }; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index b8bb763885..d825b085e7 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -169,7 +169,7 @@ namespace MWScript if (mIndex==0 && ptr.getClass().hasItemHealth (ptr)) { // health is a special case - value = ptr.getClass().getItemMaxHealth (ptr); + value = static_cast(ptr.getClass().getItemMaxHealth(ptr)); } else { value = ptr.getClass() @@ -402,7 +402,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - int bounty = runtime[0].mFloat; + int bounty = static_cast(runtime[0].mFloat); runtime.pop(); player.getClass().getNpcStats (player).setBounty(bounty); @@ -420,7 +420,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - player.getClass().getNpcStats (player).setBounty(runtime[0].mFloat + player.getClass().getNpcStats (player).getBounty()); + player.getClass().getNpcStats(player).setBounty(static_cast(runtime[0].mFloat) + player.getClass().getNpcStats(player).getBounty()); runtime.pop(); } }; @@ -1195,11 +1195,10 @@ namespace MWScript float currentValue = stats.getMagicEffects().get(mPositiveEffect).getMagnitude(); if (mNegativeEffect != -1) currentValue -= stats.getMagicEffects().get(mNegativeEffect).getMagnitude(); - currentValue = int(currentValue); int arg = runtime[0].mInteger; runtime.pop(); - stats.getMagicEffects().modifyBase(mPositiveEffect, (arg - currentValue)); + stats.getMagicEffects().modifyBase(mPositiveEffect, (arg - static_cast(currentValue))); } }; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 7af35a9ff6..f87983ce88 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -212,7 +212,7 @@ namespace MWScript if (!ptr.isInCell()) return; - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); } @@ -287,7 +287,7 @@ namespace MWScript if (ptr.getContainerStore()) return; - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); } @@ -310,12 +310,14 @@ namespace MWScript } catch(std::exception&) { - const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); - if(cell) + const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); + int cx,cy; + MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy); + store = MWBase::Environment::get().getWorld()->getExterior(cx,cy); + if(!cell) { - int cx,cy; - MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy); - store = MWBase::Environment::get().getWorld()->getExterior(cx,cy); + runtime.getContext().report ("unknown cell (" + cellID + ")"); + std::cerr << "unknown cell (" << cellID << ")\n"; } } if(store) @@ -330,15 +332,11 @@ namespace MWScript // except for when you position the player, then degrees must be used. // See "Morrowind Scripting for Dummies (9th Edition)" pages 50 and 54 for reference. if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr()) - zRot = zRot/60.; + zRot = zRot/60.0f; MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); ptr.getClass().adjustPosition(ptr, false); } - else - { - throw std::runtime_error (std::string("unknown cell (") + cellID + ")"); - } } }; @@ -354,7 +352,7 @@ namespace MWScript if (!ptr.isInCell()) return; - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true); } @@ -373,7 +371,7 @@ namespace MWScript // another morrowind oddity: player will be moved to the exterior cell at this location, // non-player actors will move within the cell they are in. MWWorld::Ptr updated; - if (ptr.getRefData().getHandle() == "player") + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { MWWorld::CellStore* cell = MWBase::Environment::get().getWorld()->getExterior(cx,cy); MWBase::Environment::get().getWorld()->moveObject(ptr,cell,x,y,z); @@ -391,7 +389,7 @@ namespace MWScript // except for when you position the player, then degrees must be used. // See "Morrowind Scripting for Dummies (9th Edition)" pages 50 and 54 for reference. if(ptr != MWBase::Environment::get().getWorld()->getPlayerPtr()) - zRot = zRot/60.; + zRot = zRot/60.0f; MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); ptr.getClass().adjustPosition(ptr, false); } @@ -426,11 +424,13 @@ namespace MWScript catch(std::exception&) { const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); - if(cell) + int cx,cy; + MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy); + store = MWBase::Environment::get().getWorld()->getExterior(cx,cy); + if(!cell) { - int cx,cy; - MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy); - store = MWBase::Environment::get().getWorld()->getExterior(cx,cy); + runtime.getContext().report ("unknown cell (" + cellID + ")"); + std::cerr << "unknown cell (" << cellID << ")\n"; } } if(store) @@ -446,10 +446,6 @@ namespace MWScript MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos); placed.getClass().adjustPosition(placed, true); } - else - { - throw std::runtime_error ( std::string("unknown cell (") + cellID + ")"); - } } }; diff --git a/apps/openmw/mwscript/transformationextensions.hpp b/apps/openmw/mwscript/transformationextensions.hpp index a25cc0c3d8..7a4d29e06c 100644 --- a/apps/openmw/mwscript/transformationextensions.hpp +++ b/apps/openmw/mwscript/transformationextensions.hpp @@ -20,4 +20,4 @@ namespace MWScript } } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index bc467acff8..0185d3ecc1 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -30,7 +30,7 @@ int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; return stream->read(buf, buf_size); } - catch (std::exception& e) + catch (std::exception& ) { return 0; } @@ -43,7 +43,7 @@ int FFmpeg_Decoder::writePacket(void *user_data, uint8_t *buf, int buf_size) Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; return stream->write(buf, buf_size); } - catch (std::exception& e) + catch (std::exception& ) { return 0; } @@ -57,11 +57,11 @@ int64_t FFmpeg_Decoder::seek(void *user_data, int64_t offset, int whence) if(whence == AVSEEK_SIZE) return stream->size(); if(whence == SEEK_SET) - stream->seek(offset); + stream->seek(static_cast(offset)); else if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); + stream->seek(static_cast(stream->tell()+offset)); else if(whence == SEEK_END) - stream->seek(stream->size()+offset); + stream->seek(static_cast(stream->size()+offset)); else return -1; diff --git a/apps/openmw/mwsound/loudness.cpp b/apps/openmw/mwsound/loudness.cpp index c64913b1fd..0077919840 100644 --- a/apps/openmw/mwsound/loudness.cpp +++ b/apps/openmw/mwsound/loudness.cpp @@ -8,7 +8,7 @@ namespace MWSound void analyzeLoudness(const std::vector &data, int sampleRate, ChannelConfig chans, SampleType type, std::vector &out, float valuesPerSecond) { - int samplesPerSegment = sampleRate / valuesPerSecond; + int samplesPerSegment = static_cast(sampleRate / valuesPerSecond); int numSamples = bytesToFrames(data.size(), chans, type); int advance = framesToBytes(1, chans, type); diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index bc94789456..1b3dced801 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -801,7 +801,7 @@ const CachedSound& OpenAL_Output::getBuffer(const std::string &fname) decoder->close(); CachedSound cached; - analyzeLoudness(data, srate, chans, type, cached.mLoudnessVector, loudnessFPS); + analyzeLoudness(data, srate, chans, type, cached.mLoudnessVector, static_cast(loudnessFPS)); alGenBuffers(1, &buf); throwALerror(); @@ -885,7 +885,7 @@ MWBase::SoundPtr OpenAL_Output::playSound(const std::string &fname, float vol, f offset=1; alSourcei(src, AL_BUFFER, buf); - alSourcef(src, AL_SEC_OFFSET, sound->getLength()*offset/pitch); + alSourcef(src, AL_SEC_OFFSET, static_cast(sound->getLength()*offset / pitch)); alSourcePlay(src); throwALerror(); @@ -910,7 +910,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre sound.reset(new OpenAL_Sound3D(*this, src, buf, pos, vol, basevol, pitch, min, max, flags)); if (extractLoudness) - sound->setLoudnessVector(cached.mLoudnessVector, loudnessFPS); + sound->setLoudnessVector(cached.mLoudnessVector, static_cast(loudnessFPS)); } catch(std::exception&) { @@ -929,7 +929,7 @@ MWBase::SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre offset=1; alSourcei(src, AL_BUFFER, buf); - alSourcef(src, AL_SEC_OFFSET, sound->getLength()*offset/pitch); + alSourcef(src, AL_SEC_OFFSET, static_cast(sound->getLength()*offset / pitch)); alSourcePlay(src); throwALerror(); diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index be12bfbecb..1a95d61505 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -69,7 +69,7 @@ namespace MWSound OpenAL_Output(SoundManager &mgr); virtual ~OpenAL_Output(); - class StreamThread; + struct StreamThread; std::auto_ptr mStreamThread; friend class OpenAL_Sound; diff --git a/apps/openmw/mwsound/sound.cpp b/apps/openmw/mwsound/sound.cpp index b3105a82c2..8b6bfda822 100644 --- a/apps/openmw/mwsound/sound.cpp +++ b/apps/openmw/mwsound/sound.cpp @@ -7,7 +7,7 @@ namespace MWSound { if (mLoudnessVector.empty()) return 0.f; - int index = getTimeOffset() * mLoudnessFPS; + int index = static_cast(getTimeOffset() * mLoudnessFPS); index = std::max(0, std::min(index, int(mLoudnessVector.size()-1))); diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index a9a999a5cb..4f5c210bbe 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -13,7 +13,7 @@ namespace MWSound { class SoundManager; - class Sound_Decoder; + struct Sound_Decoder; class Sound; class Sound_Output diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 0bc155118f..06c40dd8e8 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/statemanager.hpp" @@ -106,7 +108,7 @@ namespace MWSound MWBase::World* world = MWBase::Environment::get().getWorld(); const ESM::Sound *snd = world->getStore().get().find(soundId); - volume *= pow(10.0, (snd->mData.mVolume/255.0*3348.0 - 3348.0) / 2000.0); + volume *= static_cast(pow(10.0, (snd->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0)); if(snd->mData.mMinRange == 0 && snd->mData.mMaxRange == 0) { @@ -224,7 +226,7 @@ namespace MWSound if(!filelist.size()) return; - int i = rand()%filelist.size(); + int i = OEngine::Misc::Rng::rollDice(filelist.size()); // Don't play the same music track twice in a row if (filelist[i] == mLastPlayedMusic) @@ -477,7 +479,7 @@ namespace MWSound while(snditer != mActiveSounds.end()) { if(snditer->second.first != MWWorld::Ptr() && - snditer->second.first.getCellRef().getRefId() != "player" && + snditer->second.first != MWBase::Environment::get().getWorld()->getPlayerPtr() && snditer->second.first.getCell() == cell) { snditer->first->stop(); @@ -559,7 +561,7 @@ namespace MWSound if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound) return; - float a = std::rand() / (double)RAND_MAX; + float a = OEngine::Misc::Rng::rollClosedProbability(); // NOTE: We should use the "Minimum Time Between Environmental Sounds" and // "Maximum Time Between Environmental Sounds" fallback settings here. sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a); @@ -588,7 +590,7 @@ namespace MWSound return; } - int r = (int)(rand()/((double)RAND_MAX+1) * total); + int r = OEngine::Misc::Rng::rollDice(total); int pos = 0; soundIter = regn->mSoundList.begin(); diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index 0fe061e5ce..1c360fd4dd 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -20,7 +20,7 @@ void MWWorld::Action::execute (const Ptr& actor) { if (!mSoundId.empty()) { - if (mKeepSound && actor.getRefData().getHandle()=="player") + if (mKeepSound && actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) MWBase::Environment::get().getSoundManager()->playSound(mSoundId, 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Normal,mSoundOffset); else diff --git a/apps/openmw/mwworld/actionopen.cpp b/apps/openmw/mwworld/actionopen.cpp index e9d8b47161..0df451b18a 100644 --- a/apps/openmw/mwworld/actionopen.cpp +++ b/apps/openmw/mwworld/actionopen.cpp @@ -3,8 +3,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwgui/container.hpp" - #include "../mwmechanics/disease.hpp" #include "class.hpp" @@ -25,7 +23,6 @@ namespace MWWorld MWMechanics::diseaseContact(actor, getTarget()); - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); - MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget(), mLoot); + MWBase::Environment::get().getWindowManager()->openContainer(getTarget(), mLoot); } } diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index 0a4e2d6c9c..cd0471a0ea 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -4,13 +4,8 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" -#include "../mwworld/player.hpp" - #include "../mwmechanics/npcstats.hpp" -#include "../mwgui/bookwindow.hpp" -#include "../mwgui/scrollwindow.hpp" - #include "player.hpp" #include "class.hpp" #include "esmstore.hpp" @@ -33,27 +28,22 @@ namespace MWWorld return; } + bool showTakeButton = (getTarget().getContainerStore() != &actor.getClass().getContainerStore(actor)); + LiveCellRef *ref = getTarget().get(); if (ref->mBase->mData.mIsScroll) - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Scroll); - MWBase::Environment::get().getWindowManager()->getScrollWindow()->open(getTarget()); - } + MWBase::Environment::get().getWindowManager()->showScroll(getTarget(), showTakeButton); else - { - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book); - MWBase::Environment::get().getWindowManager()->getBookWindow()->open(getTarget()); - } + MWBase::Environment::get().getWindowManager()->showBook(getTarget(), showTakeButton); - MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats (player); + MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats (actor); // Skill gain from books if (ref->mBase->mData.mSkillID >= 0 && ref->mBase->mData.mSkillID < ESM::Skill::Length && !npcStats.hasBeenUsed (ref->mBase->mId)) { - MWWorld::LiveCellRef *playerRef = player.get(); + MWWorld::LiveCellRef *playerRef = actor.get(); const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().get().find ( diff --git a/apps/openmw/mwworld/actionrepair.cpp b/apps/openmw/mwworld/actionrepair.cpp index a86dc38b1c..699440a01c 100644 --- a/apps/openmw/mwworld/actionrepair.cpp +++ b/apps/openmw/mwworld/actionrepair.cpp @@ -19,7 +19,6 @@ namespace MWWorld return; } - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair); MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget()); } } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 545bbd4b31..7da7c187d9 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -407,8 +407,6 @@ namespace MWWorld if (mState==State_Preloaded) mIds.clear(); - std::cout << "loading cell " << mCell->getDescription() << std::endl; - loadRefs (store, esm); mState = State_Loaded; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index afc5ed6356..6fa9ba9b69 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -454,4 +454,9 @@ namespace MWWorld { return -1; } + + int Class::getEffectiveArmorRating(const Ptr &ptr, const Ptr &actor) const + { + throw std::runtime_error("class does not support armor ratings"); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 380d2a34b5..782aa78151 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -347,6 +347,9 @@ namespace MWWorld virtual std::string getPrimaryFaction (const MWWorld::Ptr& ptr) const; virtual int getPrimaryFactionRank (const MWWorld::Ptr& ptr) const; + + /// Get the effective armor rating, factoring in the actor's skills, for the given armor. + virtual int getEffectiveArmorRating(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; }; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index c2906e4474..d4aadc6c7a 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -185,7 +185,7 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find( ptr1.getClass().getEnchantment(ptr1)); - float maxCharge = enchantment->mData.mCharge; + float maxCharge = static_cast(enchantment->mData.mCharge); float enchantCharge1 = ptr1.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr1.getCellRef().getEnchantmentCharge(); float enchantCharge2 = ptr2.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr2.getCellRef().getEnchantmentCharge(); if (enchantCharge1 != maxCharge || enchantCharge2 != maxCharge) @@ -210,7 +210,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string & { MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count); // a bit pointless to set owner for the player - if (actorPtr.getRefData().getHandle() != "player") + if (actorPtr != MWBase::Environment::get().getWorld()->getPlayerPtr()) return add(ref.getPtr(), count, actorPtr, true); else return add(ref.getPtr(), count, actorPtr, false); diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 36c198f010..5d9beecb65 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -124,7 +124,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) mIds[Misc::StringUtils::lowerCase (id)] = n.val; } } - listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000); + listener->setProgress(static_cast(esm.getFileOffset() / (float)esm.getFileSize() * 1000)); } } diff --git a/apps/openmw/mwworld/failedaction.cpp b/apps/openmw/mwworld/failedaction.cpp index 7c8ef8c7bf..cf5a2a5c2f 100644 --- a/apps/openmw/mwworld/failedaction.cpp +++ b/apps/openmw/mwworld/failedaction.cpp @@ -13,7 +13,7 @@ namespace MWWorld void FailedAction::executeImp(const Ptr &actor) { - if(actor.getRefData().getHandle() == "player" && !mMessage.empty()) + if(actor == MWBase::Environment::get().getWorld()->getPlayerPtr() && !mMessage.empty()) MWBase::Environment::get().getWindowManager()->messageBox(mMessage); } } diff --git a/apps/openmw/mwworld/failedaction.hpp b/apps/openmw/mwworld/failedaction.hpp index c69d620230..f248ee3bd7 100644 --- a/apps/openmw/mwworld/failedaction.hpp +++ b/apps/openmw/mwworld/failedaction.hpp @@ -17,4 +17,4 @@ namespace MWWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 020f9561a5..2de3abc750 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -10,6 +10,9 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" + +#include "../mwgui/inventorywindow.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/spellcasting.hpp" @@ -133,7 +136,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, setOwner); // Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves - if (actorPtr.getRefData().getHandle() != "player" + if (actorPtr != MWBase::Environment::get().getWorld()->getPlayerPtr() && !(actorPtr.getClass().isNpc() && actorPtr.getClass().getNpcStats(actorPtr).isWerewolf())) { std::string type = itemPtr.getTypeName(); @@ -175,7 +178,7 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor); updateMagicEffects(actor); } @@ -188,7 +191,7 @@ void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) mUpdatesEnabled = true; - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor); updateMagicEffects(actor); } @@ -318,7 +321,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) if (changed) { mSlots.swap (slots_); - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor); updateMagicEffects(actor); flagAsModified(); } @@ -364,7 +367,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) // Roll some dice, one for each effect params.resize(enchantment.mEffects.mList.size()); for (unsigned int i=0; i (std::rand()) / RAND_MAX; + params[i].mRandom = OEngine::Misc::Rng::rollClosedProbability(); // Try resisting each effect int i=0; @@ -503,7 +506,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor // If an armor/clothing item is removed, try to find a replacement, // but not for the player nor werewolves. - if ((actor.getRefData().getHandle() != "player") + if ((actor != MWBase::Environment::get().getWorld()->getPlayerPtr()) && !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())) { std::string type = item.getTypeName(); @@ -535,7 +538,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c { retval = restack(*it); - if (actor.getRefData().getHandle() == "player") + if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) { // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared const std::string& script = it->getClass().getScript(*it); @@ -549,7 +552,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c } } - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor); updateMagicEffects(actor); return retval; @@ -576,12 +579,18 @@ void MWWorld::InventoryStore::setListener(InventoryStoreListener *listener, cons updateMagicEffects(actor); } -void MWWorld::InventoryStore::fireEquipmentChangedEvent() +void MWWorld::InventoryStore::fireEquipmentChangedEvent(const Ptr& actor) { if (!mUpdatesEnabled) return; if (mListener) mListener->equipmentChanged(); + + // if player, update inventory window + if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) + { + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView(); + } } void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisitor &visitor) @@ -630,7 +639,7 @@ void MWWorld::InventoryStore::updateRechargingItems() it->getClass().getEnchantment(*it)); if (enchantment->mData.mType == ESM::Enchantment::WhenUsed || enchantment->mData.mType == ESM::Enchantment::WhenStrikes) - mRechargingItems.push_back(std::make_pair(it, enchantment->mData.mCharge)); + mRechargingItems.push_back(std::make_pair(it, static_cast(enchantment->mData.mCharge))); } } } diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 9a154373a1..6b906207e1 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -111,7 +111,7 @@ namespace MWWorld void updateMagicEffects(const Ptr& actor); void updateRechargingItems(); - void fireEquipmentChangedEvent(); + void fireEquipmentChangedEvent(const Ptr& actor); virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const; virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory); diff --git a/apps/openmw/mwworld/localscripts.hpp b/apps/openmw/mwworld/localscripts.hpp index 840243fffc..9d612cb33c 100644 --- a/apps/openmw/mwworld/localscripts.hpp +++ b/apps/openmw/mwworld/localscripts.hpp @@ -8,7 +8,7 @@ namespace MWWorld { - struct ESMStore; + class ESMStore; class CellStore; class RefData; diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index 30b4fe353b..b926c57992 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -64,4 +64,4 @@ MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const std::string& } mPtr.getRefData().setCount(count); -} \ No newline at end of file +} diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 8f3560a691..58718074ee 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -97,13 +97,13 @@ namespace MWWorld if (mAutoMove) value = 1; - ptr.getClass().getMovementSettings (ptr).mPosition[1] = value; + ptr.getClass().getMovementSettings(ptr).mPosition[1] = static_cast(value); } void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - ptr.getClass().getMovementSettings (ptr).mPosition[0] = value; + ptr.getClass().getMovementSettings(ptr).mPosition[0] = static_cast(value); } void Player::setForwardBackward (int value) @@ -115,13 +115,13 @@ namespace MWWorld if (mAutoMove) value = 1; - ptr.getClass().getMovementSettings (ptr).mPosition[1] = value; + ptr.getClass().getMovementSettings(ptr).mPosition[1] = static_cast(value); } void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - ptr.getClass().getMovementSettings (ptr).mPosition[2] = value; + ptr.getClass().getMovementSettings(ptr).mPosition[2] = static_cast(value); } void Player::setRunState(bool run) diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index c97e4e3a50..acbe819f1e 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -68,7 +68,7 @@ namespace MWWorld { float height = 0; if (OEngine::Physic::PhysicActor* actor = mPhysEngine.getCharacter(caster.getRefData().getHandle())) - height = actor->getHalfExtents().z * 2 * 0.75; // Spawn at 0.75 * ActorHeight + height = actor->getHalfExtents().z * 2 * 0.75f; // Spawn at 0.75 * ActorHeight Ogre::Vector3 pos(caster.getRefData().getPosition().pos); pos.z += height; diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index 4d928dacf1..c97d2e6d1e 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -12,7 +12,7 @@ namespace MWWorld { class ContainerStore; class CellStore; - class LiveCellRefBase; + struct LiveCellRefBase; /// \brief Pointer to a LiveCellRef diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index c2a5e5f837..14a315a81b 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -59,7 +59,7 @@ namespace MWWorld } RefData::RefData (const ESM::ObjectState& objectState) - : mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled), + : mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled != 0), mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0), mChanged(true), // Loading from a savegame -> assume changed mDeleted(false) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index f03f65b36e..8d689240b6 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -199,7 +199,7 @@ namespace MWWorld (*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY() ); - if (land) + if (land && land->mDataTypes&ESM::Land::DATA_VHGT) mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY()); } @@ -219,6 +219,8 @@ namespace MWWorld if(result.second) { + std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl; + float verts = ESM::Land::LAND_SIZE; float worldsize = ESM::Land::REAL_SIZE; @@ -490,8 +492,6 @@ namespace MWWorld loadingListener->setProgressRange(refsToLoad); // Load cell. - std::cout << "cellName: " << cell->getCell()->mName << std::endl; - loadCell (cell, loadingListener); changePlayerCell(cell, position, true); diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index a155a37609..d6aeeb51ed 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -7,6 +7,8 @@ #include #include +#include + #include #include @@ -29,7 +31,7 @@ namespace MWWorld virtual bool eraseStatic(const std::string &id) {return false;} virtual void clearDynamic() {} - virtual void write (ESM::ESMWriter& writer) const {} + virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const {} virtual void read (ESM::ESMReader& reader, const std::string& id) {} ///< Read into dynamic storage @@ -178,7 +180,7 @@ namespace MWWorld std::vector results; std::for_each(mShared.begin(), mShared.end(), GetRecords(id, &results)); if(!results.empty()) - return results[int(std::rand()/((double)RAND_MAX+1)*results.size())]; + return results[OEngine::Misc::Rng::rollDice(results.size())]; return NULL; } @@ -234,7 +236,7 @@ namespace MWWorld int getDynamicSize() const { - return mDynamic.size(); + return static_cast (mDynamic.size()); // truncated from unsigned __int64 if _MSC_VER && _WIN64 } void listIdentifier(std::vector &list) const { @@ -364,19 +366,6 @@ namespace MWWorld inserted.first->second = scpt; } - template <> - inline void Store::load(ESM::ESMReader &esm, const std::string &id) { - ESM::StartScript s; - s.load(esm); - s.mId = Misc::StringUtils::toLower(s.mScript); - - std::pair inserted = mStatic.insert(std::make_pair(s.mId, s)); - if (inserted.second) - mShared.push_back(&inserted.first->second); - else - inserted.first->second = s; - } - template <> class Store : public StoreBase { @@ -555,6 +544,9 @@ namespace MWWorld if (left.first == right.first) return left.second > right.second; + // Exterior cells are listed in descending, row-major order, + // this is a workaround for an ambiguous chargen_plank reference in the vanilla game. + // there is one at -22,16 and one at -2,-9, the latter should be used. return left.first > right.first; } }; diff --git a/apps/openmw/mwworld/timestamp.cpp b/apps/openmw/mwworld/timestamp.cpp index a73ed7ca59..bd07b91f37 100644 --- a/apps/openmw/mwworld/timestamp.cpp +++ b/apps/openmw/mwworld/timestamp.cpp @@ -33,7 +33,7 @@ namespace MWWorld mHour = static_cast (std::fmod (hours, 24)); - mDay += hours / 24; + mDay += static_cast(hours / 24); return *this; } diff --git a/apps/openmw/mwworld/timestamp.hpp b/apps/openmw/mwworld/timestamp.hpp index 54cd40baf7..36d11cee06 100644 --- a/apps/openmw/mwworld/timestamp.hpp +++ b/apps/openmw/mwworld/timestamp.hpp @@ -3,7 +3,7 @@ namespace ESM { - class TimeStamp; + struct TimeStamp; } namespace MWWorld diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 4440ed030e..a9ca8e72b5 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -3,6 +3,8 @@ #include "weather.hpp" +#include + #include #include "../mwbase/environment.hpp" @@ -142,7 +144,7 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa * These values are fallbacks attached to weather. */ mNightStart = mSunsetTime + mSunsetDuration; - mNightEnd = mSunriseTime - 0.5; + mNightEnd = mSunriseTime - 0.5f; mDayStart = mSunriseTime + mSunriseDuration; mDayEnd = mSunsetTime; @@ -368,7 +370,7 @@ void WeatherManager::transition(float factor) mResult.mParticleEffect = other.mParticleEffect; mResult.mRainSpeed = other.mRainSpeed; mResult.mRainFrequency = other.mRainFrequency; - mResult.mAmbientSoundVolume = 2*(factor-0.5); + mResult.mAmbientSoundVolume = 2*(factor-0.5f); mResult.mEffectFade = mResult.mAmbientSoundVolume; mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID; } @@ -376,7 +378,7 @@ void WeatherManager::transition(float factor) void WeatherManager::update(float duration, bool paused) { - float timePassed = mTimePassed; + float timePassed = static_cast(mTimePassed); mTimePassed = 0; mWeatherUpdateTime -= timePassed; @@ -454,9 +456,9 @@ void WeatherManager::update(float duration, bool paused) } Vector3 final( - cos( theta ), + static_cast(cos(theta)), -0.268f, // approx tan( -15 degrees ) - sin( theta ) ); + static_cast(sin(theta))); mRendering->setSunDirection( final, is_night ); } @@ -488,8 +490,8 @@ void WeatherManager::update(float duration, bool paused) moonHeight); Vector3 secunda( - (moonHeight - 1) * facing * 1.25, - (1 - moonHeight) * facing * 0.8, + (moonHeight - 1) * facing * 1.25f, + (1 - moonHeight) * facing * 0.8f, moonHeight); mRendering->getSkyManager()->setMasserDirection(masser); @@ -526,7 +528,7 @@ void WeatherManager::update(float duration, bool paused) if (mThunderSoundDelay <= 0) { // pick a random sound - int sound = rand() % 4; + int sound = OEngine::Misc::Rng::rollDice(4); std::string* soundName = NULL; if (sound == 0) soundName = &mThunderSoundID0; else if (sound == 1) soundName = &mThunderSoundID1; @@ -542,7 +544,7 @@ void WeatherManager::update(float duration, bool paused) mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold ); else { - mThunderChanceNeeded = rand() % 100; + mThunderChanceNeeded = static_cast(OEngine::Misc::Rng::rollDice(100)); mThunderChance = 0; mRendering->getSkyManager()->setLightningStrength( 0.f ); } @@ -624,7 +626,7 @@ std::string WeatherManager::nextWeather(const ESM::Region* region) const * 70% will be greater than 30 (in theory). */ - int chance = (rand() % 100) + 1; // 1..100 + int chance = OEngine::Misc::Rng::rollDice(100) + 1; // 1..100 int sum = 0; unsigned int i = 0; for (; i < probability.size(); ++i) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8a2b67bfcb..013386f8f9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include #include #include @@ -570,9 +572,9 @@ namespace MWWorld if (name=="gamehour") setHour (value); else if (name=="day") - setDay (value); + setDay(static_cast(value)); else if (name=="month") - setMonth (value); + setMonth(static_cast(value)); else mGlobalVariables[name].setFloat (value); } @@ -800,7 +802,7 @@ namespace MWWorld void World::advanceTime (double hours) { - MWBase::Environment::get().getMechanicsManager()->advanceTime(hours*3600); + MWBase::Environment::get().getMechanicsManager()->advanceTime(static_cast(hours * 3600)); mWeatherManager->advanceTime (hours); @@ -808,7 +810,7 @@ namespace MWWorld setHour (hours); - int days = hours / 24; + int days = static_cast(hours / 24); if (days>0) mGlobalVariables["dayspassed"].setInteger ( @@ -820,15 +822,15 @@ namespace MWWorld if (hour<0) hour = 0; - int days = hour / 24; + int days = static_cast(hour / 24); hour = std::fmod (hour, 24); - mGlobalVariables["gamehour"].setFloat (hour); + mGlobalVariables["gamehour"].setFloat(static_cast(hour)); mRendering->skySetHour (hour); - mWeatherManager->setHour (hour); + mWeatherManager->setHour(static_cast(hour)); if (days>0) setDay (days + mGlobalVariables["day"].getInteger()); @@ -1015,25 +1017,9 @@ namespace MWWorld float World::getMaxActivationDistance () { if (mActivationDistanceOverride >= 0) - return mActivationDistanceOverride; + return static_cast(mActivationDistanceOverride); - return (std::max) (getNpcActivationDistance (), getObjectActivationDistance ()); - } - - float World::getNpcActivationDistance () - { - if (mActivationDistanceOverride >= 0) - return mActivationDistanceOverride; - - return getStore().get().find ("iMaxActivateDist")->getInt()*5/4; - } - - float World::getObjectActivationDistance () - { - if (mActivationDistanceOverride >= 0) - return mActivationDistanceOverride; - - return getStore().get().find ("iMaxActivateDist")->getInt(); + return getStore().get().find("iMaxActivateDist")->getFloat() * 5 / 4; } MWWorld::Ptr World::getFacedObject() @@ -1362,7 +1348,7 @@ namespace MWWorld pos.pos[2] += dist; actor.getRefData().setPosition(pos); - Ogre::Vector3 traced = mPhysics->traceDown(actor, dist*1.1); + Ogre::Vector3 traced = mPhysics->traceDown(actor, dist*1.1f); moveObject(actor, actor.getCell(), traced.x, traced.y, traced.z); } @@ -1383,8 +1369,8 @@ namespace MWWorld { const int cellSize = 8192; - x = cellSize * cellX; - y = cellSize * cellY; + x = static_cast(cellSize * cellX); + y = static_cast(cellSize * cellY); if (centre) { @@ -1397,8 +1383,8 @@ namespace MWWorld { const int cellSize = 8192; - cellX = std::floor(x/cellSize); - cellY = std::floor(y/cellSize); + cellX = static_cast(std::floor(x / cellSize)); + cellY = static_cast(std::floor(y / cellSize)); } void World::queueMovement(const Ptr &ptr, const Vector3 &velocity) @@ -1418,7 +1404,7 @@ namespace MWWorld PtrVelocityList::const_iterator player(results.end()); for(PtrVelocityList::const_iterator iter(results.begin());iter != results.end();++iter) { - if(iter->first.getRefData().getHandle() == "player") + if(iter->first == getPlayerPtr()) { /* Handle player last, in case a cell transition occurs */ player = iter; @@ -1617,7 +1603,7 @@ namespace MWWorld { Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNode()->getPosition(); const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle()); - if(actor) playerPos.z += 1.85*actor->getHalfExtents().z; + if(actor) playerPos.z += 1.85f * actor->getHalfExtents().z; Ogre::Quaternion playerOrient = Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X) * Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y); @@ -2009,7 +1995,7 @@ namespace MWWorld bool World::isSubmerged(const MWWorld::Ptr &object) const { - return isUnderwater(object, 1.0/mSwimHeightScale); + return isUnderwater(object, 1.0f/mSwimHeightScale); } bool World::isSwimming(const MWWorld::Ptr &object) const @@ -2240,7 +2226,7 @@ namespace MWWorld if (healthPerSecond > 0.0f) { - if (actor.getRefData().getHandle() == "player") + if (actor == getPlayerPtr()) MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) @@ -2271,7 +2257,7 @@ namespace MWWorld if (healthPerSecond > 0.0f) { - if (actor.getRefData().getHandle() == "player") + if (actor == getPlayerPtr()) MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) @@ -2367,8 +2353,8 @@ namespace MWWorld Ogre::Vector3 halfExt2 = actor2->getHalfExtents(); const float* pos2 = targetActor.getRefData().getPosition().pos; - btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z*2*0.9); // eye level - btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z*2*0.9); + btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z*2*0.9f); // eye level + btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z*2*0.9f); std::pair result = mPhysEngine->rayTest(from, to,false); if(result.first == "") return true; @@ -2528,7 +2514,7 @@ namespace MWWorld // the following is just for reattaching the camera properly. mRendering->rebuildPtr(actor); - if(actor.getRefData().getHandle() == "player") + if(actor == getPlayerPtr()) { // Update the GUI only when called on the player MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager(); @@ -2587,7 +2573,7 @@ namespace MWWorld const Store &gmst = getStore().get(); MWMechanics::NpcStats &stats = actor.getClass().getNpcStats(actor); - stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getFloat()); + stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getInt()); } bool World::getGodModeState() @@ -3067,8 +3053,8 @@ namespace MWWorld float fCrimeGoldDiscountMult = getStore().get().find("fCrimeGoldDiscountMult")->getFloat(); float fCrimeGoldTurnInMult = getStore().get().find("fCrimeGoldTurnInMult")->getFloat(); - int discount = bounty * fCrimeGoldDiscountMult; - int turnIn = bounty * fCrimeGoldTurnInMult; + int discount = static_cast(bounty * fCrimeGoldDiscountMult); + int turnIn = static_cast(bounty * fCrimeGoldTurnInMult); if (bounty > 0) { @@ -3149,7 +3135,7 @@ namespace MWWorld const ESM::CreatureLevList* list = getStore().get().find(creatureList); int iNumberCreatures = getStore().get().find("iNumberCreatures")->getInt(); - int numCreatures = 1 + std::rand()/ (static_cast (RAND_MAX) + 1) * iNumberCreatures; // [1, iNumberCreatures] + int numCreatures = 1 + OEngine::Misc::Rng::rollDice(iNumberCreatures); // [1, iNumberCreatures] for (int i=0; i (RAND_MAX) + 1) * 3; // [0, 2] + int roll = OEngine::Misc::Rng::rollDice(3); // [0, 2] modelName << roll; std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str()); @@ -3231,7 +3217,7 @@ namespace MWWorld else areaStatic = getStore().get().find ("VFX_DefaultArea"); - mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, effectIt->mArea); + mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, static_cast(effectIt->mArea)); // Play explosion sound (make sure to use NoTrack, since we will delete the projectile now) static const std::string schools[] = { @@ -3247,7 +3233,7 @@ namespace MWWorld // Get the actors in range of the effect std::vector objects; MWBase::Environment::get().getMechanicsManager()->getObjectsInRange( - origin, feetToGameUnits(effectIt->mArea), objects); + origin, feetToGameUnits(static_cast(effectIt->mArea)), objects); for (std::vector::iterator affected = objects.begin(); affected != objects.end(); ++affected) toApply[*affected].push_back(*effectIt); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 1db86f7383..63d6506de0 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -115,9 +115,6 @@ namespace MWWorld void performUpdateSceneQueries (); void getFacedHandle(std::string& facedHandle, float maxDistance, bool ignorePlayer=true); - float getNpcActivationDistance (); - float getObjectActivationDistance (); - void removeContainerScripts(const Ptr& reference); void addContainerScripts(const Ptr& reference, CellStore* cell); void PCDropped (const Ptr& item); diff --git a/apps/wizard/componentselectionpage.cpp b/apps/wizard/componentselectionpage.cpp index 1fcde78579..21a5c58d9b 100644 --- a/apps/wizard/componentselectionpage.cpp +++ b/apps/wizard/componentselectionpage.cpp @@ -156,9 +156,13 @@ bool Wizard::ComponentSelectionPage::validatePage() int Wizard::ComponentSelectionPage::nextId() const { +#ifdef OPENMW_USE_UNSHIELD if (isCommitPage()) { return MainWizard::Page_Installation; } else { return MainWizard::Page_Import; } +#else + return MainWizard::Page_Import; +#endif } diff --git a/apps/wizard/existinginstallationpage.cpp b/apps/wizard/existinginstallationpage.cpp index 83ea20f5a8..f821b38ba3 100644 --- a/apps/wizard/existinginstallationpage.cpp +++ b/apps/wizard/existinginstallationpage.cpp @@ -29,11 +29,7 @@ void Wizard::ExistingInstallationPage::initializePage() QStringList paths(mWizard->mInstallations.keys()); // Hide the default item if there are installations to choose from - if (paths.isEmpty()) { - installationsList->item(0)->setHidden(false); - } else { - installationsList->item(0)->setHidden(true); - } + installationsList->item(0)->setHidden(!paths.isEmpty()); foreach (const QString &path, paths) { QListWidgetItem *item = new QListWidgetItem(path); diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index a1370b1253..a61daa5a4c 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -62,6 +62,12 @@ Wizard::MainWizard::MainWizard(QWidget *parent) : setupLauncherSettings(); setupInstallations(); setupPages(); + + const boost::filesystem::path& installedPath = mCfgMgr.getInstallPath(); + if (!installedPath.empty()) + { + addInstallation(toQString(installedPath)); + } } Wizard::MainWizard::~MainWizard() @@ -71,7 +77,7 @@ Wizard::MainWizard::~MainWizard() void Wizard::MainWizard::setupLog() { - QString logPath(QString::fromUtf8(mCfgMgr.getLogPath().string().c_str())); + QString logPath(toQString(mCfgMgr.getLogPath())); logPath.append(QLatin1String("wizard.log")); QFile file(logPath); @@ -93,7 +99,7 @@ void Wizard::MainWizard::setupLog() void Wizard::MainWizard::addLogText(const QString &text) { - QString logPath(QString::fromUtf8(mCfgMgr.getLogPath().string().c_str())); + QString logPath(toQString(mCfgMgr.getLogPath())); logPath.append(QLatin1String("wizard.log")); QFile file(logPath); @@ -121,8 +127,8 @@ void Wizard::MainWizard::addLogText(const QString &text) void Wizard::MainWizard::setupGameSettings() { - QString userPath(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); - QString globalPath(QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str())); + QString userPath(toQString(mCfgMgr.getUserConfigPath())); + QString globalPath(toQString(mCfgMgr.getGlobalPath())); QString message(tr("

Could not open %1 for reading

\

Please make sure you have the right permissions \ and try again.

")); @@ -181,7 +187,7 @@ void Wizard::MainWizard::setupGameSettings() void Wizard::MainWizard::setupLauncherSettings() { - QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); + QString path(toQString(mCfgMgr.getUserConfigPath())); path.append(QLatin1String(Config::LauncherSettings::sLauncherConfigFileName)); QString message(tr("

Could not open %1 for reading

\ @@ -228,7 +234,7 @@ void Wizard::MainWizard::runSettingsImporter() QString path(field(QLatin1String("installation.path")).toString()); // Create the file if it doesn't already exist, else the importer will fail - QString userPath(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); + QString userPath(toQString(mCfgMgr.getUserConfigPath())); QFile file(userPath + QLatin1String("openmw.cfg")); if (!file.exists()) { @@ -387,7 +393,7 @@ void Wizard::MainWizard::writeSettings() mGameSettings.removeDataDir(path); mGameSettings.addDataDir(path); - QString userPath(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); + QString userPath(toQString(mCfgMgr.getUserConfigPath())); QDir dir(userPath); if (!dir.exists()) { @@ -460,3 +466,8 @@ bool Wizard::MainWizard::findFiles(const QString &name, const QString &path) return (dir.entryList().contains(name + QLatin1String(".esm"), Qt::CaseInsensitive) && dir.entryList().contains(name + QLatin1String(".bsa"), Qt::CaseInsensitive)); } + +QString Wizard::MainWizard::toQString(const boost::filesystem::path& path) +{ + return QString::fromUtf8(path.string().c_str()); +} diff --git a/apps/wizard/mainwizard.hpp b/apps/wizard/mainwizard.hpp index c22f20c259..7f6e48a876 100644 --- a/apps/wizard/mainwizard.hpp +++ b/apps/wizard/mainwizard.hpp @@ -59,6 +59,8 @@ namespace Wizard void addLogText(const QString &text); private: + /// convert boost::filesystem::path to QString + QString toQString(const boost::filesystem::path& path); void setupLog(); void setupGameSettings(); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a49e54dd3e..38fcd88e3e 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -62,7 +62,7 @@ add_component_dir (esm loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile - aisequence magiceffects util custommarkerstate stolenitems + aisequence magiceffects util custommarkerstate stolenitems transport ) add_component_dir (esmterrain @@ -160,7 +160,11 @@ include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) -target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES}) +target_link_libraries(components + ${Boost_LIBRARIES} + ${OGRE_LIBRARIES} + ${OENGINE_LIBRARY} +) if (GIT_CHECKOUT) add_dependencies (components git-version) diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 0958c8f0c2..3bf73ede27 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -79,7 +79,7 @@ void BSAFile::readHeader() bfs::ifstream input(bfs::path(filename), std::ios_base::binary); // Total archive size - size_t fsize = 0; + std::streamoff fsize = 0; if(input.seekg(0, std::ios_base::end)) { fsize = input.tellg(); @@ -111,7 +111,7 @@ void BSAFile::readHeader() // Each file must take up at least 21 bytes of data in the bsa. So // if files*21 overflows the file size then we are guaranteed that // the archive is corrupt. - if((filenum*21 > fsize -12) || (dirsize+8*filenum > fsize -12) ) + if((filenum*21 > unsigned(fsize -12)) || (dirsize+8*filenum > unsigned(fsize -12)) ) fail("Directory information larger than entire archive"); // Read the offset info into a temporary buffer diff --git a/components/bsa/resources.cpp b/components/bsa/resources.cpp index d06b3b4852..b66da1a766 100644 --- a/components/bsa/resources.cpp +++ b/components/bsa/resources.cpp @@ -50,4 +50,4 @@ void Bsa::registerResources (const Files::Collections& collections, throw std::runtime_error(message.str()); } } -} \ No newline at end of file +} diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 7eaca5c02a..dc36b58d82 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -324,7 +324,7 @@ namespace Compiler mNextOperand = false; mOperands.push_back ('l'); - return 2; + return true; } } diff --git a/components/compiler/extensions0.hpp b/components/compiler/extensions0.hpp index d51507711f..83f3a44fa6 100644 --- a/components/compiler/extensions0.hpp +++ b/components/compiler/extensions0.hpp @@ -78,4 +78,4 @@ namespace Compiler } } -#endif \ No newline at end of file +#endif diff --git a/components/compiler/nullerrorhandler.cpp b/components/compiler/nullerrorhandler.cpp index 3071701e8a..ee28847059 100644 --- a/components/compiler/nullerrorhandler.cpp +++ b/components/compiler/nullerrorhandler.cpp @@ -3,4 +3,4 @@ void Compiler::NullErrorHandler::report (const std::string& message, const TokenLoc& loc, Type type) {} -void Compiler::NullErrorHandler::report (const std::string& message, Type type) {} \ No newline at end of file +void Compiler::NullErrorHandler::report (const std::string& message, Type type) {} diff --git a/components/compiler/opcodes.cpp b/components/compiler/opcodes.cpp index 8617062d63..03081dff9f 100644 --- a/components/compiler/opcodes.cpp +++ b/components/compiler/opcodes.cpp @@ -10,4 +10,4 @@ namespace Compiler "playerviewswitch", "vanitymode" }; } -} \ No newline at end of file +} diff --git a/components/compiler/quickfileparser.cpp b/components/compiler/quickfileparser.cpp index f3d8063b2f..4e9f76e13c 100644 --- a/components/compiler/quickfileparser.cpp +++ b/components/compiler/quickfileparser.cpp @@ -49,4 +49,4 @@ bool Compiler::QuickFileParser::parseSpecial (int code, const TokenLoc& loc, Sca void Compiler::QuickFileParser::parseEOF (Scanner& scanner) { -} \ No newline at end of file +} diff --git a/components/config/launchersettings.hpp b/components/config/launchersettings.hpp index cbe21c54a6..c5eefb22a5 100644 --- a/components/config/launchersettings.hpp +++ b/components/config/launchersettings.hpp @@ -17,7 +17,7 @@ namespace Config /// \return names of all Content Lists in the launcher's .cfg file. QStringList getContentLists(); - /// Set initally selected content list to match values from openmw.cfg, creating if necessary + /// Set initially selected content list to match values from openmw.cfg, creating if necessary void setContentList(const GameSettings& gameSettings); /// Create a Content List (or replace if it already exists) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 7850b2cd60..62f6d90141 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -110,9 +110,9 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex &index if (!file) return Qt::NoItemFlags; - //game files are not shown + //game files can always be checked if (file->isGameFile()) - return Qt::NoItemFlags; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; Qt::ItemFlags returnFlags; @@ -449,7 +449,7 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) ToUTF8::Utf8Encoder encoder = ToUTF8::calculateEncoding(mEncoding.toStdString()); fileReader.setEncoder(&encoder); - fileReader.open(dir.absoluteFilePath(path).toStdString()); + fileReader.open(std::string(dir.absoluteFilePath(path).toUtf8().constData())); EsmFile *file = new EsmFile(path); @@ -463,7 +463,7 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) file->setDescription(QString::fromUtf8(fileReader.getDesc().c_str())); // HACK - // Load order constraint of Bloodmoon.esm needing Tribunal.esm is missing + // Load order constraint of Bloodmoon.esm needing Tribunal.esm is missing // from the file supplied by Bethesda, so we have to add it ourselves if (file->fileName().compare("Bloodmoon.esm", Qt::CaseInsensitive) == 0) { diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index 2363ae477a..e3093d5685 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -183,6 +183,7 @@ void ContentSelectorView::ContentSelector::setGameFileSelected(int index, bool s void ContentSelectorView::ContentSelector::slotAddonTableItemActivated(const QModelIndex &index) { + // toggles check state when an AddOn file is double clicked or activated by keyboard QModelIndex sourceIndex = mAddonProxyModel->mapToSource (index); if (!mContentModel->isEnabled (sourceIndex)) diff --git a/components/esm/cellid.hpp b/components/esm/cellid.hpp index 40bc552e00..44a1b387a2 100644 --- a/components/esm/cellid.hpp +++ b/components/esm/cellid.hpp @@ -28,4 +28,4 @@ namespace ESM bool operator!= (const CellId& left, const CellId& right); } -#endif \ No newline at end of file +#endif diff --git a/components/esm/containerstate.cpp b/components/esm/containerstate.cpp index 5dcf17733e..80ad5cbdc8 100644 --- a/components/esm/containerstate.cpp +++ b/components/esm/containerstate.cpp @@ -13,4 +13,4 @@ void ESM::ContainerState::save (ESMWriter &esm, bool inInventory) const ObjectState::save (esm, inInventory); mInventory.save (esm); -} \ No newline at end of file +} diff --git a/components/esm/esmcommon.hpp b/components/esm/esmcommon.hpp index 54b18aeaf3..d90a3444dd 100644 --- a/components/esm/esmcommon.hpp +++ b/components/esm/esmcommon.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace ESM { diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index ebbc935f6f..2df2a86b31 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -2,7 +2,7 @@ #define OPENMW_ESM_READER_H #include -#include +#include #include #include #include diff --git a/components/esm/globalscript.cpp b/components/esm/globalscript.cpp index 467fe54a14..0129f8eb7d 100644 --- a/components/esm/globalscript.cpp +++ b/components/esm/globalscript.cpp @@ -26,4 +26,4 @@ void ESM::GlobalScript::save (ESMWriter &esm) const esm.writeHNT ("RUN_", mRunning); esm.writeHNOString ("TARG", mTargetId); -} \ No newline at end of file +} diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp index 999c3f92a1..3481189c37 100644 --- a/components/esm/loadcont.cpp +++ b/components/esm/loadcont.cpp @@ -87,7 +87,7 @@ namespace ESM mModel.clear(); mScript.clear(); mWeight = 0; - mFlags = 0; + mFlags = 0x8; // set default flag value mInventory.mList.clear(); } } diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 2e9f924b7c..50c47349ca 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -10,11 +10,12 @@ namespace ESM { void Creature::load(ESMReader &esm) { - mPersistent = esm.getRecordFlags() & 0x0400; + mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mAiPackage.mList.clear(); mInventory.mList.clear(); mSpells.mList.clear(); + mTransport.mList.clear(); mScale = 1.f; mHasAI = false; @@ -59,6 +60,10 @@ namespace ESM { esm.getHExact(&mAiData, sizeof(mAiData)); mHasAI = true; break; + case ESM::FourCC<'D','O','D','T'>::value: + case ESM::FourCC<'D','N','A','M'>::value: + mTransport.add(esm); + break; case AI_Wander: case AI_Activate: case AI_Escort: @@ -94,6 +99,7 @@ namespace ESM { if (mHasAI) { esm.writeHNT("AIDT", mAiData, sizeof(mAiData)); } + mTransport.save(esm); mAiPackage.save(esm); } @@ -120,5 +126,11 @@ namespace ESM { mAiData.blank(); mAiData.mServices = 0; mAiPackage.mList.clear(); + mTransport.mList.clear(); + } + + const std::vector& Creature::getTransport() const + { + return mTransport.mList; } } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index e459dded72..1b02aa0abc 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -6,6 +6,7 @@ #include "loadcont.hpp" #include "spelllist.hpp" #include "aipackage.hpp" +#include "transport.hpp" namespace ESM { @@ -92,6 +93,9 @@ struct Creature bool mHasAI; AIData mAiData; AIPackageList mAiPackage; + Transport mTransport; + + const std::vector& getTransport() const; void load(ESMReader &esm); void save(ESMWriter &esm) const; diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index 6b66ac832d..398b8047fd 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -12,7 +12,7 @@ class ESMReader; class ESMWriter; /* - * Game setting, with automatic cleaning of "dirty" entries. + * Game setting * */ diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index ae73eee521..b1c01fcba6 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -11,7 +11,7 @@ namespace ESM void Land::LandData::save(ESMWriter &esm) { if (mDataTypes & Land::DATA_VNML) { - esm.writeHNT("VNML", mNormals, sizeof(VNML)); + esm.writeHNT("VNML", mNormals, sizeof(mNormals)); } if (mDataTypes & Land::DATA_VHGT) { VHGT offsets; diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index d90b4816dd..751c7f252b 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -10,11 +10,11 @@ namespace ESM void NPC::load(ESMReader &esm) { - mPersistent = esm.getRecordFlags() & 0x0400; + mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mSpells.mList.clear(); mInventory.mList.clear(); - mTransport.clear(); + mTransport.mList.clear(); mAiPackage.mList.clear(); bool hasNpdt = false; @@ -81,14 +81,8 @@ namespace ESM mHasAI= true; break; case ESM::FourCC<'D','O','D','T'>::value: - { - Dest dodt; - esm.getHExact(&dodt.mPos, 24); - mTransport.push_back(dodt); - break; - } case ESM::FourCC<'D','N','A','M'>::value: - mTransport.back().mCellName = esm.getHString(); + mTransport.add(esm); break; case AI_Wander: case AI_Activate: @@ -131,11 +125,8 @@ namespace ESM esm.writeHNT("AIDT", mAiData, sizeof(mAiData)); } - typedef std::vector::const_iterator DestIter; - for (DestIter it = mTransport.begin(); it != mTransport.end(); ++it) { - esm.writeHNT("DODT", it->mPos, sizeof(it->mPos)); - esm.writeHNOCString("DNAM", it->mCellName); - } + mTransport.save(esm); + mAiPackage.save(esm); } @@ -177,7 +168,7 @@ namespace ESM mSpells.mList.clear(); mAiData.blank(); mHasAI = false; - mTransport.clear(); + mTransport.mList.clear(); mAiPackage.mList.clear(); mName.clear(); mModel.clear(); @@ -198,4 +189,9 @@ namespace ESM else // NPC_DEFAULT return mNpdt52.mRank; } + + const std::vector& NPC::getTransport() const + { + return mTransport.mList; + } } diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 9dc3be513a..b535b91b01 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -9,6 +9,7 @@ #include "aipackage.hpp" #include "spelllist.hpp" #include "loadskil.hpp" +#include "transport.hpp" namespace ESM { @@ -98,12 +99,6 @@ struct NPC char mUnknown1, mUnknown2, mUnknown3; int mGold; }; // 12 bytes - - struct Dest - { - Position mPos; - std::string mCellName; - }; #pragma pack(pop) unsigned char mNpdtType; @@ -122,7 +117,10 @@ struct NPC AIData mAiData; bool mHasAI; - std::vector mTransport; + Transport mTransport; + + const std::vector& getTransport() const; + AIPackageList mAiPackage; std::string mId, mName, mModel, mRace, mClass, mFaction, mScript; diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 61f56b5117..fc0974c9d8 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -10,22 +10,22 @@ namespace ESM Pathgrid::Point& Pathgrid::Point::operator=(const float rhs[3]) { - mX = rhs[0]; - mY = rhs[1]; - mZ = rhs[2]; + mX = static_cast(rhs[0]); + mY = static_cast(rhs[1]); + mZ = static_cast(rhs[2]); mAutogenerated = 0; mConnectionNum = 0; mUnknown = 0; return *this; } Pathgrid::Point::Point(const float rhs[3]) - : mAutogenerated(0), + : mX(static_cast(rhs[0])), + mY(static_cast(rhs[1])), + mZ(static_cast(rhs[2])), + mAutogenerated(0), mConnectionNum(0), mUnknown(0) { - mX = rhs[0]; - mY = rhs[1]; - mZ = rhs[2]; } Pathgrid::Point::Point():mX(0),mY(0),mZ(0),mAutogenerated(0), mConnectionNum(0),mUnknown(0) diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index 967c0d0d73..e88454d4c1 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -15,7 +15,7 @@ namespace ESM int Race::MaleFemaleF::getValue (bool male) const { - return male ? mMale : mFemale; + return static_cast(male ? mMale : mFemale); } void Race::load(ESMReader &esm) diff --git a/components/esm/loadsscr.cpp b/components/esm/loadsscr.cpp index 816075b7e3..7380dd0a7f 100644 --- a/components/esm/loadsscr.cpp +++ b/components/esm/loadsscr.cpp @@ -23,7 +23,7 @@ namespace ESM hasData = true; break; case ESM::FourCC<'N','A','M','E'>::value: - mScript = esm.getHString(); + mId = esm.getHString(); hasName = true; break; default: @@ -38,7 +38,11 @@ namespace ESM void StartScript::save(ESMWriter &esm) const { esm.writeHNString("DATA", mData); - esm.writeHNString("NAME", mScript); + esm.writeHNString("NAME", mId); } + void StartScript::blank() + { + mData.clear(); + } } diff --git a/components/esm/loadsscr.hpp b/components/esm/loadsscr.hpp index d09ad883eb..1420d16c47 100644 --- a/components/esm/loadsscr.hpp +++ b/components/esm/loadsscr.hpp @@ -22,11 +22,13 @@ struct StartScript static unsigned int sRecordId; std::string mData; - std::string mId, mScript; + std::string mId; // Load a record and add it to the list void load(ESMReader &esm); void save(ESMWriter &esm) const; + + void blank(); }; } diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 2bb817332d..ed90b04751 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -10,7 +10,7 @@ namespace ESM void Static::load(ESMReader &esm) { - mPersistent = esm.getRecordFlags() & 0x0400; + mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mModel = esm.getHNString("MODL"); } diff --git a/components/esm/queststate.cpp b/components/esm/queststate.cpp index e938267255..c8cff7adc9 100644 --- a/components/esm/queststate.cpp +++ b/components/esm/queststate.cpp @@ -16,4 +16,4 @@ void ESM::QuestState::save (ESMWriter &esm) const esm.writeHNString ("YETO", mTopic); esm.writeHNT ("QSTA", mState); esm.writeHNT ("QFIN", mFinished); -} \ No newline at end of file +} diff --git a/components/esm/statstate.hpp b/components/esm/statstate.hpp index 801d0ce826..f57ba9f30e 100644 --- a/components/esm/statstate.hpp +++ b/components/esm/statstate.hpp @@ -40,7 +40,7 @@ namespace ESM // mDamage was changed to a float; ensure backwards compatibility T oldDamage = 0; esm.getHNOT(oldDamage, "STDA"); - mDamage = oldDamage; + mDamage = static_cast(oldDamage); esm.getHNOT (mDamage, "STDF"); diff --git a/components/esm/transport.cpp b/components/esm/transport.cpp new file mode 100644 index 0000000000..da0a5f7676 --- /dev/null +++ b/components/esm/transport.cpp @@ -0,0 +1,33 @@ +#include "transport.hpp" + +#include +#include + +namespace ESM +{ + + void Transport::add(ESMReader &esm) + { + if (esm.retSubName().val == ESM::FourCC<'D','O','D','T'>::value) + { + Dest dodt; + esm.getHExact(&dodt.mPos, 24); + mList.push_back(dodt); + } + else if (esm.retSubName().val == ESM::FourCC<'D','N','A','M'>::value) + { + mList.back().mCellName = esm.getHString(); + } + } + + void Transport::save(ESMWriter &esm) const + { + typedef std::vector::const_iterator DestIter; + for (DestIter it = mList.begin(); it != mList.end(); ++it) + { + esm.writeHNT("DODT", it->mPos, sizeof(it->mPos)); + esm.writeHNOCString("DNAM", it->mCellName); + } + } + +} diff --git a/components/esm/transport.hpp b/components/esm/transport.hpp new file mode 100644 index 0000000000..10d4013f72 --- /dev/null +++ b/components/esm/transport.hpp @@ -0,0 +1,36 @@ +#ifndef OPENMW_COMPONENTS_ESM_TRANSPORT_H +#define OPENMW_COMPONENTS_ESM_TRANSPORT_H + +#include +#include + +#include "defs.hpp" + +namespace ESM +{ + + class ESMReader; + class ESMWriter; + + /// List of travel service destination. Shared by CREA and NPC_ records. + struct Transport + { + + struct Dest + { + Position mPos; + std::string mCellName; + }; + + std::vector mList; + + /// Load one destination, assumes the subrecord name was already read + void add(ESMReader &esm); + + void save(ESMWriter &esm) const; + + }; + +} + +#endif diff --git a/components/esm/variantimp.cpp b/components/esm/variantimp.cpp index fd068fc196..eeb0bf04f3 100644 --- a/components/esm/variantimp.cpp +++ b/components/esm/variantimp.cpp @@ -128,7 +128,7 @@ int ESM::VariantIntegerData::getInteger (bool default_) const float ESM::VariantIntegerData::getFloat (bool default_) const { - return mValue; + return static_cast(mValue); } void ESM::VariantIntegerData::setInteger (int value) @@ -202,7 +202,7 @@ void ESM::VariantIntegerData::write (ESMWriter& esm, Variant::Format format, Var { if (type==VT_Short || type==VT_Long) { - float value = mValue; + float value = static_cast(mValue); esm.writeHNString ("FNAM", type==VT_Short ? "s" : "l"); esm.writeHNT ("FLTV", value); } @@ -262,7 +262,7 @@ float ESM::VariantFloatData::getFloat (bool default_) const void ESM::VariantFloatData::setInteger (int value) { - mValue = value; + mValue = static_cast(value); } void ESM::VariantFloatData::setFloat (float value) diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index d4a0a0df2c..763f0f4e05 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -27,8 +27,8 @@ namespace ESMTerrain assert(origin.x == (int) origin.x); assert(origin.y == (int) origin.y); - int cellX = origin.x; - int cellY = origin.y; + int cellX = static_cast(origin.x); + int cellY = static_cast(origin.y); const ESM::Land* land = getLand(cellX, cellY); if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT)) @@ -135,10 +135,10 @@ namespace ESMTerrain assert(origin.x == (int) origin.x); assert(origin.y == (int) origin.y); - int startX = origin.x; - int startY = origin.y; + int startX = static_cast(origin.x); + int startY = static_cast(origin.y); - size_t numVerts = size*(ESM::Land::LAND_SIZE-1)/increment + 1; + size_t numVerts = static_cast(size*(ESM::Land::LAND_SIZE - 1) / increment + 1); colours.resize(numVerts*numVerts*4); positions.resize(numVerts*numVerts*3); @@ -175,12 +175,12 @@ namespace ESMTerrain vertX = vertX_; for (int row=rowStart; row(vertX*numVerts * 3 + vertY * 3)] = ((vertX / float(numVerts - 1) - 0.5f) * size * 8192); + positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 1)] = ((vertY / float(numVerts - 1) - 0.5f) * size * 8192); if (land) - positions[vertX*numVerts*3 + vertY*3 + 2] = land->mLandData->mHeights[col*ESM::Land::LAND_SIZE+row]; + positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = land->mLandData->mHeights[col*ESM::Land::LAND_SIZE + row]; else - positions[vertX*numVerts*3 + vertY*3 + 2] = -2048; + positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = -2048; if (land && land->mDataTypes&ESM::Land::DATA_VNML) { @@ -202,9 +202,9 @@ namespace ESMTerrain assert(normal.z > 0); - normals[vertX*numVerts*3 + vertY*3] = normal.x; - normals[vertX*numVerts*3 + vertY*3 + 1] = normal.y; - normals[vertX*numVerts*3 + vertY*3 + 2] = normal.z; + normals[static_cast(vertX*numVerts * 3 + vertY * 3)] = normal.x; + normals[static_cast(vertX*numVerts * 3 + vertY * 3 + 1)] = normal.y; + normals[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = normal.z; if (land && land->mDataTypes&ESM::Land::DATA_VCLR) { @@ -226,7 +226,7 @@ namespace ESMTerrain color.a = 1; Ogre::uint32 rsColor; Ogre::Root::getSingleton().getRenderSystem()->convertColourValue(color, &rsColor); - memcpy(&colours[vertX*numVerts*4 + vertY*4], &rsColor, sizeof(Ogre::uint32)); + memcpy(&colours[static_cast(vertX*numVerts * 4 + vertY * 4)], &rsColor, sizeof(Ogre::uint32)); ++vertX; } @@ -293,7 +293,7 @@ namespace ESMTerrain { out.push_back(Terrain::LayerCollection()); out.back().mTarget = *it; - getBlendmapsImpl((*it)->getSize(), (*it)->getCenter(), pack, out.back().mBlendmaps, out.back().mLayers); + getBlendmapsImpl(static_cast((*it)->getSize()), (*it)->getCenter(), pack, out.back().mBlendmaps, out.back().mLayers); } } @@ -311,8 +311,8 @@ namespace ESMTerrain // and interpolate the rest of the cell by hand? :/ Ogre::Vector2 origin = chunkCenter - Ogre::Vector2(chunkSize/2.f, chunkSize/2.f); - int cellX = origin.x; - int cellY = origin.y; + int cellX = static_cast(origin.x); + int cellY = static_cast(origin.y); // Save the used texture indices so we know the total number of textures // and number of required blend maps @@ -343,7 +343,7 @@ namespace ESMTerrain int numTextures = textureIndices.size(); // numTextures-1 since the base layer doesn't need blending - int numBlendmaps = pack ? std::ceil((numTextures-1) / 4.f) : (numTextures-1); + int numBlendmaps = pack ? static_cast(std::ceil((numTextures - 1) / 4.f)) : (numTextures - 1); int channels = pack ? 4 : 1; @@ -364,7 +364,7 @@ namespace ESMTerrain { UniqueTextureId id = getVtexIndexAt(cellX, cellY, x, y); int layerIndex = textureIndicesMap.find(id)->second; - int blendIndex = (pack ? std::floor((layerIndex-1)/4.f) : layerIndex-1); + int blendIndex = (pack ? static_cast(std::floor((layerIndex - 1) / 4.f)) : layerIndex - 1); int channel = pack ? std::max(0, (layerIndex-1) % 4) : 0; if (blendIndex == i) @@ -379,11 +379,11 @@ namespace ESMTerrain float Storage::getHeightAt(const Ogre::Vector3 &worldPos) { - int cellX = std::floor(worldPos.x / 8192.f); - int cellY = std::floor(worldPos.y / 8192.f); + int cellX = static_cast(std::floor(worldPos.x / 8192.f)); + int cellY = static_cast(std::floor(worldPos.y / 8192.f)); ESM::Land* land = getLand(cellX, cellY); - if (!land) + if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT)) return -2048; // Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition @@ -465,8 +465,9 @@ namespace ESMTerrain Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture) { // Already have this cached? - if (mLayerInfoMap.find(texture) != mLayerInfoMap.end()) - return mLayerInfoMap[texture]; + std::map::iterator found = mLayerInfoMap.find(texture); + if (found != mLayerInfoMap.end()) + return found->second; Terrain::LayerInfo info; info.mParallax = false; @@ -518,7 +519,7 @@ namespace ESMTerrain float Storage::getCellWorldSize() { - return ESM::Land::REAL_SIZE; + return static_cast(ESM::Land::REAL_SIZE); } int Storage::getCellVertices() diff --git a/components/files/androidpath.cpp b/components/files/androidpath.cpp index 009bd98a2c..84886f4734 100644 --- a/components/files/androidpath.cpp +++ b/components/files/androidpath.cpp @@ -31,6 +31,7 @@ JNIEXPORT void JNICALL Java_ui_activity_GameActivity_getPathToJni(JNIEnv *env, j { jboolean iscopy; Buffer::setData((env)->GetStringUTFChars(prompt, &iscopy)); + (env)->DeleteLocalRef(prompt); } namespace diff --git a/components/files/macospath.cpp b/components/files/macospath.cpp index 3e53f53061..6e794796f9 100644 --- a/components/files/macospath.cpp +++ b/components/files/macospath.cpp @@ -7,10 +7,6 @@ #include #include -/** - * FIXME: Someone with MacOS system should check this and correct if necessary - */ - namespace { boost::filesystem::path getUserHome() @@ -49,9 +45,8 @@ boost::filesystem::path MacOsPath::getUserConfigPath() const boost::filesystem::path MacOsPath::getUserDataPath() const { - // TODO: probably wrong? boost::filesystem::path userPath (getUserHome()); - userPath /= "Library/Preferences/"; + userPath /= "Library/Application Support/"; return userPath / mName; } diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 6b58304a0f..0df782702d 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -94,18 +94,8 @@ boost::filesystem::path WindowsPath::getInstallPath() const HKEY hKey; - BOOL f64 = FALSE; - LPCTSTR regkey; - if ((IsWow64Process(GetCurrentProcess(), &f64) && f64) || sizeof(void*) == 8) - { - regkey = "SOFTWARE\\Wow6432Node\\Bethesda Softworks\\Morrowind"; - } - else - { - regkey = "SOFTWARE\\Bethesda Softworks\\Morrowind"; - } - - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(regkey), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) + LPCTSTR regkey = TEXT("SOFTWARE\\Bethesda Softworks\\Morrowind"); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) { //Key existed, let's try to read the install dir std::vector buf(512); @@ -115,6 +105,7 @@ boost::filesystem::path WindowsPath::getInstallPath() const { installPath = &buf[0]; } + RegCloseKey(hKey); } return installPath; diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 17c630fd9f..eb7dd901d7 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -20,12 +20,12 @@ namespace { size_t i = 0; unsigned long unicode; - size_t todo; + size_t numbytes; unsigned char ch = utf8[i++]; if (ch <= 0x7F) { unicode = ch; - todo = 0; + numbytes = 0; } else if (ch <= 0xBF) { @@ -34,23 +34,23 @@ namespace else if (ch <= 0xDF) { unicode = ch&0x1F; - todo = 1; + numbytes = 1; } else if (ch <= 0xEF) { unicode = ch&0x0F; - todo = 2; + numbytes = 2; } else if (ch <= 0xF7) { unicode = ch&0x07; - todo = 3; + numbytes = 3; } else { throw std::logic_error("not a UTF-8 string"); } - for (size_t j = 0; j < todo; ++j) + for (size_t j = 0; j < numbytes; ++j) { unsigned char ch = utf8[i++]; if (ch < 0x80 || ch > 0xBF) @@ -288,7 +288,7 @@ namespace Gui 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(data[i].width, data[i].height)); + code->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); // More hacks! The french game uses several win1252 characters that are not included // in the cp437 encoding of the font. Fall back to similar available characters. @@ -334,7 +334,7 @@ namespace Gui 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(data[i].width, data[i].height)); + code->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); } } @@ -350,7 +350,7 @@ namespace Gui cursorCode->addAttribute("advance", data[i].width); cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + MyGUI::utility::toString((fontSize-data[i].ascent))); - cursorCode->addAttribute("size", MyGUI::IntSize(data[i].width, data[i].height)); + cursorCode->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); } // Question mark, use for NotDefined marker (used for glyphs not existing in the font) @@ -365,7 +365,7 @@ namespace Gui cursorCode->addAttribute("advance", data[i].width); cursorCode->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + MyGUI::utility::toString((fontSize-data[i].ascent))); - cursorCode->addAttribute("size", MyGUI::IntSize(data[i].width, data[i].height)); + cursorCode->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); } } diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 1da8cf6956..f566a54997 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -12,6 +12,8 @@ #include "runtime.hpp" #include "defines.hpp" +#include + namespace Interpreter { inline std::string formatMessage (const std::string& message, Runtime& runtime) @@ -140,15 +142,13 @@ namespace Interpreter virtual void execute (Runtime& runtime) { - double r = static_cast (std::rand()) / RAND_MAX; // [0, 1) - Type_Integer limit = runtime[0].mInteger; if (limit<0) throw std::runtime_error ( "random: argument out of range (Don't be so negative!)"); - Type_Integer value = static_cast (r*limit); // [o, limit) + Type_Integer value = OEngine::Misc::Rng::rollDice(limit); // [o, limit) runtime[0].mInteger = value; } diff --git a/components/nif/data.hpp b/components/nif/data.hpp index d9de12fb54..1fa94d9c2a 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -234,7 +234,7 @@ class NiVisData : public Record public: struct VisData { float time; - char isSet; + bool isSet; }; std::vector mVis; @@ -245,7 +245,7 @@ public: for(size_t i = 0;i < mVis.size();i++) { mVis[i].time = nif->getFloat(); - mVis[i].isSet = nif->getChar(); + mVis[i].isSet = nif->getChar() != 0; } } }; diff --git a/components/nif/node.cpp b/components/nif/node.cpp index fb68da548d..d99d157ae2 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -38,7 +38,10 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop, wireprop = static_cast(pr); else if (pr->recType == Nif::RC_NiStencilProperty) stencilprop = static_cast(pr); - else + // the following are unused by the MW engine + else if (pr->recType != Nif::RC_NiFogProperty + && pr->recType != Nif::RC_NiDitherProperty + && pr->recType != Nif::RC_NiShadeProperty) std::cerr<< "Unhandled property type: "<recName <string == "MRK" && !mShowMarkers) - // Marker objects. These are only visible in the - // editor. + else if (sd->string == "MRK" && !mShowMarkers && raycasting) + { + // Marker objects should be invisible, but still have collision. + // Except in the editor, the marker objects are visible. return; + } } } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index 56d98834da..0d81d84b6b 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -38,8 +38,8 @@ namespace Nif { class Node; - class Transformation; - class NiTriShape; + struct Transformation; + struct NiTriShape; } namespace NifBullet diff --git a/components/nifogre/mesh.hpp b/components/nifogre/mesh.hpp index 731e49c903..69b3f2f78b 100644 --- a/components/nifogre/mesh.hpp +++ b/components/nifogre/mesh.hpp @@ -10,7 +10,7 @@ namespace Nif { - class NiTriShape; + struct NiTriShape; } namespace NifOgre diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 17df7a3cdc..0009c9f836 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -379,7 +379,7 @@ public: return mData.back().isSet; } - static void setVisible(Ogre::Node *node, int vis) + static void setVisible(Ogre::Node *node, bool vis) { // Skinned meshes are attached to the scene node, not the bone. // We use the Node's user data to connect it with the mesh. @@ -746,16 +746,17 @@ private: { if (ctrl->flags & Nif::NiNode::ControllerFlag_Active) { + bool isAnimationAutoPlay = (animflags & Nif::NiNode::AnimFlag_AutoPlay) != 0; if(ctrl->recType == Nif::RC_NiUVController) { const Nif::NiUVController *uv = static_cast(ctrl.getPtr()); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? + Ogre::ControllerValueRealPtr srcval(isAnimationAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(entity, uv->data.getPtr(), &scene->mMaterialControllerMgr)); - UVController::Function* function = OGRE_NEW UVController::Function(uv, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + UVController::Function* function = OGRE_NEW UVController::Function(uv, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); @@ -765,13 +766,13 @@ private: { const Nif::NiGeomMorpherController *geom = static_cast(ctrl.getPtr()); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? + Ogre::ControllerValueRealPtr srcval(isAnimationAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value( entity, geom->data.getPtr(), geom->recIndex)); - GeomMorpherController::Function* function = OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + GeomMorpherController::Function* function = OGRE_NEW GeomMorpherController::Function(geom, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); @@ -796,7 +797,8 @@ private: const Nif::NiStencilProperty *stencilprop = NULL; node->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, stencilprop); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? + bool isAnimationAutoPlay = (animflags & Nif::NiNode::AnimFlag_AutoPlay) != 0; + Ogre::ControllerValueRealPtr srcval(isAnimationAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); @@ -809,7 +811,7 @@ private: { const Nif::NiAlphaController *alphaCtrl = static_cast(ctrls.getPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW AlphaController::Value(movable, alphaCtrl->data.getPtr(), &scene->mMaterialControllerMgr)); - AlphaController::Function* function = OGRE_NEW AlphaController::Function(alphaCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + AlphaController::Function* function = OGRE_NEW AlphaController::Function(alphaCtrl, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); @@ -818,7 +820,7 @@ private: { const Nif::NiMaterialColorController *matCtrl = static_cast(ctrls.getPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW MaterialColorController::Value(movable, matCtrl->data.getPtr(), &scene->mMaterialControllerMgr)); - MaterialColorController::Function* function = OGRE_NEW MaterialColorController::Function(matCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + MaterialColorController::Function* function = OGRE_NEW MaterialColorController::Function(matCtrl, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); @@ -839,7 +841,7 @@ private: Ogre::ControllerValueRealPtr dstval(OGRE_NEW FlipController::Value( movable, flipCtrl, &scene->mMaterialControllerMgr)); - FlipController::Function* function = OGRE_NEW FlipController::Function(flipCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + FlipController::Function* function = OGRE_NEW FlipController::Function(flipCtrl, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); @@ -967,7 +969,7 @@ private: partsys->setCullIndividually(false); partsys->setParticleQuota(particledata->numParticles); - partsys->setKeepParticlesInLocalSpace(partflags & (Nif::NiNode::ParticleFlag_LocalSpace)); + partsys->setKeepParticlesInLocalSpace((partflags & Nif::NiNode::ParticleFlag_LocalSpace) != 0); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex); Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); @@ -1017,13 +1019,14 @@ private: createParticleInitialState(partsys, particledata, partctrl); - Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ? + bool isParticleAutoPlay = (partflags&Nif::NiNode::ParticleFlag_AutoPlay) != 0; + Ogre::ControllerValueRealPtr srcval(isParticleAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW ParticleSystemController::Value(partsys, partctrl)); ParticleSystemController::Function* function = - OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay)); + OGRE_NEW ParticleSystemController::Function(partctrl, isParticleAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); @@ -1032,7 +1035,7 @@ private: // Emitting state will be overwritten on frame update by the ParticleSystemController, // but set up an initial value anyway so the user can fast-forward particle systems // immediately after creation if desired. - partsys->setEmitting(partflags&Nif::NiNode::ParticleFlag_AutoPlay); + partsys->setEmitting(isParticleAutoPlay); } ctrl = ctrl->next; } @@ -1094,18 +1097,19 @@ private: do { if (ctrl->flags & Nif::NiNode::ControllerFlag_Active) { + bool isAnimationAutoPlay = (animflags & Nif::NiNode::AnimFlag_AutoPlay) != 0; if(ctrl->recType == Nif::RC_NiVisController) { const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex); Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? + Ogre::ControllerValueRealPtr srcval(isAnimationAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr())); - VisController::Function* function = OGRE_NEW VisController::Function(vis, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + VisController::Function* function = OGRE_NEW VisController::Function(vis, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); @@ -1120,11 +1124,11 @@ private: Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); // The keyframe controller will control this bone manually trgtbone->setManuallyControlled(true); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? + Ogre::ControllerValueRealPtr srcval(isAnimationAutoPlay ? Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, nif, key->data.getPtr())); - KeyframeController::Function* function = OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); + KeyframeController::Function* function = OGRE_NEW KeyframeController::Function(key, isAnimationAutoPlay); scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); Ogre::ControllerFunctionRealPtr func(function); diff --git a/components/nifogre/particles.cpp b/components/nifogre/particles.cpp index 4fec2d29eb..936bfb435f 100644 --- a/components/nifogre/particles.cpp +++ b/components/nifogre/particles.cpp @@ -12,6 +12,8 @@ #include #include +#include + /* FIXME: "Nif" isn't really an appropriate emitter name. */ class NifEmitter : public Ogre::ParticleEmitter { @@ -171,7 +173,7 @@ public: Ogre::Real& timeToLive = particle->timeToLive; #endif - Ogre::Node* emitterBone = mEmitterBones.at((int)(::rand()/(RAND_MAX+1.0)*mEmitterBones.size())); + Ogre::Node* emitterBone = mEmitterBones.at(OEngine::Misc::Rng::rollDice(mEmitterBones.size())); position = xOff + yOff + zOff + mParticleBone->_getDerivedOrientation().Inverse() * (emitterBone->_getDerivedPosition() diff --git a/components/terrain/defaultworld.cpp b/components/terrain/defaultworld.cpp index e14c64f3a0..c6f0f7136c 100644 --- a/components/terrain/defaultworld.cpp +++ b/components/terrain/defaultworld.cpp @@ -108,8 +108,8 @@ namespace Terrain storage->getBounds(mMinX, mMaxX, mMinY, mMaxY); - int origSizeX = mMaxX-mMinX; - int origSizeY = mMaxY-mMinY; + int origSizeX = static_cast(mMaxX - mMinX); + int origSizeY = static_cast(mMaxY - mMinY); // Dividing a quad tree only works well for powers of two, so round up to the nearest one int size = nextPowerOfTwo(std::max(origSizeX, origSizeY)); @@ -124,7 +124,7 @@ namespace Terrain LayersRequestData data; data.mPack = getShadersEnabled(); - mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(centerX, centerY), NULL); + mRootNode = new QuadTreeNode(this, Root, static_cast(size), Ogre::Vector2(centerX, centerY), NULL); buildQuadTree(mRootNode, data.mNodes); //loadingListener->indicateProgress(); mRootNode->initAabb(); @@ -160,7 +160,7 @@ namespace Terrain float minZ,maxZ; Ogre::Vector2 center = node->getCenter(); float cellWorldSize = getStorage()->getCellWorldSize(); - if (mStorage->getMinMaxHeights(node->getSize(), center, minZ, maxZ)) + if (mStorage->getMinMaxHeights(static_cast(node->getSize()), center, minZ, maxZ)) { Ogre::AxisAlignedBox bounds(Ogre::Vector3(-halfSize*cellWorldSize, -halfSize*cellWorldSize, minZ), Ogre::Vector3(halfSize*cellWorldSize, halfSize*cellWorldSize, maxZ)); @@ -275,7 +275,7 @@ namespace Terrain LoadResponseData* responseData = new LoadResponseData(); - getStorage()->fillVertexBuffers(node->getNativeLodLevel(), node->getSize(), node->getCenter(), getAlign(), + getStorage()->fillVertexBuffers(node->getNativeLodLevel(), static_cast(node->getSize()), node->getCenter(), getAlign(), responseData->mPositions, responseData->mNormals, responseData->mColours); return OGRE_NEW Ogre::WorkQueue::Response(req, true, Ogre::Any(responseData)); diff --git a/components/terrain/defaultworld.hpp b/components/terrain/defaultworld.hpp index 90e8cc2b6a..4caef8462f 100644 --- a/components/terrain/defaultworld.hpp +++ b/components/terrain/defaultworld.hpp @@ -84,7 +84,7 @@ namespace Terrain /// adding or removing passes. This can only be achieved by a full rebuild.) virtual void applyMaterials(bool shadows, bool splitShadows); - int getMaxBatchSize() { return mMaxBatchSize; } + int getMaxBatchSize() { return static_cast(mMaxBatchSize); } /// Wait until all background loading is complete. void syncLoad(); diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 4ff04ab93a..4d2318aa6b 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -36,7 +36,7 @@ namespace int getBlendmapIndexForLayer (int layerIndex) { - return std::floor((layerIndex-1)/4.f); + return static_cast(std::floor((layerIndex - 1) / 4.f)); } std::string getBlendmapComponentForLayer (int layerIndex) diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index f35080e7c6..b79df9f48c 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -35,7 +35,7 @@ namespace Terrain MaterialGenerator (); void setLayerList (const std::vector& layerList) { mLayerList = layerList; } - bool hasLayers() { return mLayerList.size(); } + bool hasLayers() { return mLayerList.size() > 0; } void setBlendmapList (const std::vector& blendmapList) { mBlendmapList = blendmapList; } const std::vector& getBlendmapList() { return mBlendmapList; } void setCompositeMap (const std::string& name) { mCompositeMap = name; } diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 5fce5eae91..6a99642132 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -135,7 +135,7 @@ QuadTreeNode::QuadTreeNode(DefaultWorld* terrain, ChildDirection dir, float size : mMaterialGenerator(NULL) , mIsDummy(false) , mSize(size) - , mLodLevel(Log2(mSize)) + , mLodLevel(Log2(static_cast(mSize))) , mBounds(Ogre::AxisAlignedBox::BOX_NULL) , mWorldBounds(Ogre::AxisAlignedBox::BOX_NULL) , mDirection(dir) diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index 1ecd6fcd56..e44b646004 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -95,7 +95,7 @@ namespace Terrain Ogre::SceneNode* getSceneNode() { return mSceneNode; } - int getSize() { return mSize; } + int getSize() { return static_cast(mSize); } Ogre::Vector2 getCenter() { return mCenter; } bool hasChildren() { return mChildren[0] != 0; } diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 269152e611..bb99ca23e4 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -56,16 +56,16 @@ void TerrainGrid::loadCell(int x, int y) if (mGrid.find(std::make_pair(x, y)) != mGrid.end()) return; // already loaded - Ogre::Vector2 center(x+0.5, y+0.5); + Ogre::Vector2 center(x+0.5f, y+0.5f); float minH, maxH; if (!mStorage->getMinMaxHeights(1, center, minH, maxH)) return; // no terrain defined - Ogre::Vector3 min (-0.5*mStorage->getCellWorldSize(), - -0.5*mStorage->getCellWorldSize(), + Ogre::Vector3 min (-0.5f*mStorage->getCellWorldSize(), + -0.5f*mStorage->getCellWorldSize(), minH); - Ogre::Vector3 max (0.5*mStorage->getCellWorldSize(), - 0.5*mStorage->getCellWorldSize(), + Ogre::Vector3 max (0.5f*mStorage->getCellWorldSize(), + 0.5f*mStorage->getCellWorldSize(), maxH); Ogre::AxisAlignedBox bounds(min, max); @@ -163,8 +163,8 @@ void TerrainGrid::setVisible(bool visible) Ogre::AxisAlignedBox TerrainGrid::getWorldBoundingBox (const Ogre::Vector2& center) { - int cellX = std::floor(center.x); - int cellY = std::floor(center.y); + int cellX = static_cast(std::floor(center.x)); + int cellY = static_cast(std::floor(center.y)); Grid::iterator it = mGrid.find(std::make_pair(cellX, cellY)); if (it == mGrid.end()) diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index cb9680441c..d7f9c3a382 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -84,11 +84,11 @@ std::string Utf8Encoder::getUtf8(const char* input, size_t size) // is also ok.) assert(input[size] == 0); - // TODO: The rest of this function is designed for single-character + // Note: The rest of this function is designed for single-character // input encodings only. It also assumes that the input the input - // encoding shares its first 128 values (0-127) with ASCII. These - // conditions must be checked again if you add more input encodings - // later. + // encoding shares its first 128 values (0-127) with ASCII. There are + // no plans to add more encodings to this module (we are using utf8 + // for new content files), so that shouldn't be an issue. // Compute output length, and check for pure ascii input at the same // time. diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index f3d3a2c288..8517a0303e 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -138,10 +138,10 @@ namespace Gui void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel) { //NB view offset is negative - if (mScrollView->getViewOffset().top + _rel*0.3 > 0) + if (mScrollView->getViewOffset().top + _rel*0.3f > 0) mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3)); + mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast(mScrollView->getViewOffset().top + _rel*0.3))); } void MWList::onItemSelected(MyGUI::Widget* _sender) diff --git a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp index cfc6c17b91..1a56802dae 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp +++ b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp @@ -222,7 +222,7 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame, int &sample_skip) } /* if update, update the audio clock w/pts */ - if((uint64_t)pkt->pts != AV_NOPTS_VALUE) + if(pkt->pts != AV_NOPTS_VALUE) mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts; } } diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.cpp b/extern/ogre-ffmpeg-videoplayer/videostate.cpp index 0894499b23..66c7c2ad50 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.cpp @@ -179,7 +179,7 @@ int VideoState::OgreResource_Read(void *user_data, uint8_t *buf, int buf_size) { return stream->read(buf, buf_size); } - catch (std::exception& e) + catch (std::exception& ) { return 0; } @@ -192,7 +192,7 @@ int VideoState::OgreResource_Write(void *user_data, uint8_t *buf, int buf_size) { return stream->write(buf, buf_size); } - catch (std::exception& e) + catch (std::exception& ) { return 0; } @@ -206,11 +206,11 @@ int64_t VideoState::OgreResource_Seek(void *user_data, int64_t offset, int whenc if(whence == AVSEEK_SIZE) return stream->size(); if(whence == SEEK_SET) - stream->seek(offset); + stream->seek(static_cast(offset)); else if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); + stream->seek(static_cast(stream->tell()+offset)); else if(whence == SEEK_END) - stream->seek(stream->size()+offset); + stream->seek(static_cast(stream->size() + offset)); else return -1; @@ -400,7 +400,7 @@ void VideoState::video_thread_loop(VideoState *self) self->pictq_mutex.unlock(); self->frame_last_pts = packet->pts * av_q2d((*self->video_st)->time_base); - global_video_pkt_pts = self->frame_last_pts; + global_video_pkt_pts = static_cast(self->frame_last_pts); continue; } @@ -412,9 +412,9 @@ void VideoState::video_thread_loop(VideoState *self) double pts = 0; if(packet->dts != AV_NOPTS_VALUE) - pts = packet->dts; + pts = static_cast(packet->dts); else if(pFrame->opaque && *(int64_t*)pFrame->opaque != AV_NOPTS_VALUE) - pts = *(int64_t*)pFrame->opaque; + pts = static_cast(*(int64_t*)pFrame->opaque); pts *= av_q2d((*self->video_st)->time_base); av_free_packet(packet); diff --git a/extern/oics/ICSChannelListener.h b/extern/oics/ICSChannelListener.h index d520b3bceb..a202e7e220 100644 --- a/extern/oics/ICSChannelListener.h +++ b/extern/oics/ICSChannelListener.h @@ -43,4 +43,4 @@ namespace ICS } -#endif \ No newline at end of file +#endif diff --git a/extern/oics/ICSControl.cpp b/extern/oics/ICSControl.cpp index 7c804d6eee..974d69f081 100644 --- a/extern/oics/ICSControl.cpp +++ b/extern/oics/ICSControl.cpp @@ -43,10 +43,10 @@ namespace ICS , mAxisBindable(axisBindable) , currentChangingDirection(STOP) { - + } - Control::~Control() + Control::~Control() { mAttachedChannels.clear(); } @@ -92,7 +92,7 @@ namespace ICS } void Control::setChangingDirection(ControlChangingDirection direction) - { + { currentChangingDirection = direction; mPendingActions.push_back(direction); } @@ -102,9 +102,9 @@ namespace ICS if(!mPendingActions.empty()) { size_t timedActionsCount = 0; - + std::list::iterator cached_end = mPendingActions.end(); - for(std::list::iterator it = mPendingActions.begin() ; + for(std::list::iterator it = mPendingActions.begin() ; it != cached_end ; ++it) { if( (*it) != Control::STOP ) @@ -112,14 +112,14 @@ namespace ICS timedActionsCount++; } } - + float timeSinceLastFramePart = timeSinceLastFrame / std::max(1, timedActionsCount); - for(std::list::iterator it = mPendingActions.begin() ; + for(std::list::iterator it = mPendingActions.begin() ; it != cached_end ; ++it) { if( (*it) != Control::STOP ) { - this->setValue(mValue + + this->setValue(mValue + (((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))); } else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) @@ -141,7 +141,7 @@ namespace ICS } else if( currentChangingDirection != Control::STOP ) { - this->setValue(mValue + + this->setValue(mValue + (((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame))); } else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) diff --git a/extern/oics/ICSControl.h b/extern/oics/ICSControl.h index ebf75a3fef..1ed4376524 100644 --- a/extern/oics/ICSControl.h +++ b/extern/oics/ICSControl.h @@ -34,7 +34,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace ICS { - + class DllExport Control { public: @@ -52,9 +52,10 @@ namespace ICS void setValue(float value); inline float getValue(){ return mValue; }; - inline float getInitialValue(){ return mInitialValue; }; + inline float getInitialValue(){ return mInitialValue; }; + inline void setInitialValue(float i) {mInitialValue = i;}; - void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0); + void attachChannel(Channel* channel, Channel::ChannelDirection direction, float percentage = 1.0); std::list getAttachedChannels(){ return mAttachedChannels; }; inline float getStepSize(){ return mStepSize; }; diff --git a/extern/oics/ICSControlListener.h b/extern/oics/ICSControlListener.h index 067b2d6f24..97b3940be6 100644 --- a/extern/oics/ICSControlListener.h +++ b/extern/oics/ICSControlListener.h @@ -43,4 +43,4 @@ namespace ICS } -#endif \ No newline at end of file +#endif diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index e1bd587288..2599c57614 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -60,10 +60,10 @@ namespace ICS xmlDoc = new TiXmlDocument(file.c_str()); xmlDoc->LoadFile(); - if(xmlDoc->Error()) + if(xmlDoc->Error()) { - std::ostringstream message; - message << "TinyXml reported an error reading \""+ file + "\". Row " << + std::ostringstream message; + message << "TinyXml reported an error reading \""+ file + "\". Row " << (int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " << xmlDoc->ErrorDesc() ; ICS_LOG(message.str()); @@ -81,10 +81,10 @@ namespace ICS TiXmlElement* xmlControl = xmlRoot->FirstChildElement("Control"); - size_t controlChannelCount = 0; - while(xmlControl) + size_t controlChannelCount = 0; + while(xmlControl) { - TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); + TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); while(xmlChannel) { controlChannelCount = std::max(channelCount, FromString(xmlChannel->Attribute("number"))+1); @@ -111,7 +111,7 @@ namespace ICS // // - TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter"); + TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter"); while(xmlChannelFilter) { int ch = FromString(xmlChannelFilter->Attribute("number")); @@ -133,12 +133,12 @@ namespace ICS float step = FromString(xmlInterval->Attribute("step")); ICS_LOG("Applying Bezier filter to channel [number=" - + ToString(ch) + ", startX=" - + ToString(startX) + ", startY=" - + ToString(startY) + ", midX=" - + ToString(midX) + ", midY=" - + ToString(midY) + ", endX=" - + ToString(endX) + ", endY=" + + ToString(ch) + ", startX=" + + ToString(startX) + ", startY=" + + ToString(startY) + ", midX=" + + ToString(midX) + ", midY=" + + ToString(midY) + ", endX=" + + ToString(endX) + ", endY=" + ToString(endY) + ", step=" + ToString(step) + "]"); @@ -152,8 +152,8 @@ namespace ICS xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter"); } - xmlControl = xmlRoot->FirstChildElement("Control"); - while(xmlControl) + xmlControl = xmlRoot->FirstChildElement("Control"); + while(xmlControl) { bool axisBindable = true; if(xmlControl->Attribute("axisBindable")) @@ -176,11 +176,11 @@ namespace ICS std::string value(xmlControl->Attribute("stepSize")); if(value == "MAX") { - _stepSize = ICS_MAX; + _stepSize = ICS_MAX; } else { - _stepSize = FromString(value.c_str()); + _stepSize = FromString(value.c_str()); } } else @@ -194,7 +194,7 @@ namespace ICS std::string value(xmlControl->Attribute("stepsPerSeconds")); if(value == "MAX") { - _stepsPerSeconds = ICS_MAX; + _stepsPerSeconds = ICS_MAX; } else { @@ -224,12 +224,8 @@ namespace ICS loadJoystickButtonBinders(xmlControl); - loadJoystickPOVBinders(xmlControl); - - loadJoystickSliderBinders(xmlControl); - // Attach controls to channels - TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); + TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); while(xmlChannel) { ICS_LOG("\tAttaching control to channel [number=" @@ -250,7 +246,7 @@ namespace ICS { percentage = val; } - } + } else { ICS_LOG("ERROR: attaching percentage value range is [0,1]"); @@ -338,7 +334,7 @@ namespace ICS for(std::vector::const_iterator o = mChannels.begin() ; o != mChannels.end(); ++o) { ICS::IntervalList intervals = (*o)->getIntervals(); - + if(intervals.size() > 1) // all channels have a default linear filter { TiXmlElement ChannelFilter( "ChannelFilter" ); @@ -371,7 +367,7 @@ namespace ICS ChannelFilter.InsertEndChild(XMLInterval); } - + ++interval; } @@ -401,7 +397,7 @@ namespace ICS control.SetAttribute( "autoReverseToInitialValue", "false" ); } control.SetAttribute( "initialValue", ToString((*o)->getInitialValue()).c_str() ); - + if((*o)->getStepSize() == ICS_MAX) { control.SetAttribute( "stepSize", "MAX" ); @@ -445,12 +441,12 @@ namespace ICS control.InsertEndChild(keyBinder); } - if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) + if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) != InputControlSystem/*::NamedAxis*/::UNASSIGNED) { TiXmlElement binder( "MouseBinder" ); - InputControlSystem::NamedAxis axis = + InputControlSystem::NamedAxis axis = getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE); if(axis == InputControlSystem/*::NamedAxis*/::X) { @@ -469,12 +465,12 @@ namespace ICS control.InsertEndChild(binder); } - if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) + if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) != InputControlSystem/*::NamedAxis*/::UNASSIGNED) { TiXmlElement binder( "MouseBinder" ); - InputControlSystem::NamedAxis axis = + InputControlSystem::NamedAxis axis = getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE); if(axis == InputControlSystem/*::NamedAxis*/::X) { @@ -493,7 +489,7 @@ namespace ICS control.InsertEndChild(binder); } - if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) + if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) != ICS_MAX_DEVICE_BUTTONS) { TiXmlElement binder( "MouseButtonBinder" ); @@ -519,7 +515,7 @@ namespace ICS control.InsertEndChild(binder); } - if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) + if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) != ICS_MAX_DEVICE_BUTTONS) { TiXmlElement binder( "MouseButtonBinder" ); @@ -543,153 +539,72 @@ namespace ICS } binder.SetAttribute( "direction", "DECREASE" ); control.InsertEndChild(binder); - } + } + JoystickIDList::const_iterator it = mJoystickIDList.begin(); + while(it!=mJoystickIDList.end()) + { + int deviceID = *it; + if(getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickAxisBinder" ); - JoystickIDList::const_iterator it = mJoystickIDList.begin(); - while(it != mJoystickIDList.end()) - { - int deviceId = *it; + binder.SetAttribute( "axis", ToString( + getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); - if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) - != /*NamedAxis::*/UNASSIGNED) - { - TiXmlElement binder( "JoystickAxisBinder" ); + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability - binder.SetAttribute( "axis", ToString( - getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + control.InsertEndChild(binder); + } - binder.SetAttribute( "direction", "INCREASE" ); + if(getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE) + != /*NamedAxis::*/UNASSIGNED) + { + TiXmlElement binder( "JoystickAxisBinder" ); - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } + binder.SetAttribute( "axis", ToString( + getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) - != /*NamedAxis::*/UNASSIGNED) - { - TiXmlElement binder( "JoystickAxisBinder" ); + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability - binder.SetAttribute( "axis", ToString( - getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); + control.InsertEndChild(binder); + } - binder.SetAttribute( "direction", "DECREASE" ); + if(getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "JoystickButtonBinder" ); - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } + binder.SetAttribute( "button", ToString( + getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); - if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) - != ICS_MAX_DEVICE_BUTTONS) - { - TiXmlElement binder( "JoystickButtonBinder" ); + binder.SetAttribute( "direction", "INCREASE" ); + + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability - binder.SetAttribute( "button", ToString( - getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); + control.InsertEndChild(binder); + } - binder.SetAttribute( "direction", "INCREASE" ); + if(getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE) + != ICS_MAX_DEVICE_BUTTONS) + { + TiXmlElement binder( "JoystickButtonBinder" ); - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } + binder.SetAttribute( "button", ToString( + getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) - != ICS_MAX_DEVICE_BUTTONS) - { - TiXmlElement binder( "JoystickButtonBinder" ); + binder.SetAttribute( "direction", "DECREASE" ); + + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability - binder.SetAttribute( "button", ToString( - getJoystickButtonBinding(*o, *it, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - - binder.SetAttribute( "direction", "DECREASE" ); - - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } - - if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE).index >= 0) - { - TiXmlElement binder( "JoystickPOVBinder" ); - - POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE); - - binder.SetAttribute( "pov", ToString(POVPair.index).c_str() ); - - binder.SetAttribute( "direction", "INCREASE" ); - - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - if(POVPair.axis == ICS::InputControlSystem::EastWest) - { - binder.SetAttribute( "axis", "EastWest" ); - } - else - { - binder.SetAttribute( "axis", "NorthSouth" ); - } - - control.InsertEndChild(binder); - } - - if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE).index >= 0) - { - TiXmlElement binder( "JoystickPOVBinder" ); - - POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE); - - binder.SetAttribute( "pov", ToString(POVPair.index).c_str() ); - - binder.SetAttribute( "direction", "DECREASE" ); - - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - if(POVPair.axis == ICS::InputControlSystem::EastWest) - { - binder.SetAttribute( "axis", "EastWest" ); - } - else - { - binder.SetAttribute( "axis", "NorthSouth" ); - } - - control.InsertEndChild(binder); - } - - if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) - != /*NamedAxis::*/UNASSIGNED) - { - TiXmlElement binder( "JoystickSliderBinder" ); - - binder.SetAttribute( "slider", ToString( - getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); - - binder.SetAttribute( "direction", "INCREASE" ); - - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } - - if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) - != /*NamedAxis::*/UNASSIGNED) - { - TiXmlElement binder( "JoystickSliderBinder" ); - - binder.SetAttribute( "slider", ToString( - getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - - binder.SetAttribute( "direction", "DECREASE" ); - - binder.SetAttribute( "deviceId", ToString(deviceId).c_str() ); - - control.InsertEndChild(binder); - } - - ++it; - } + control.InsertEndChild(binder); + } + it++; + } std::list channels = (*o)->getAttachedChannels(); @@ -700,19 +615,19 @@ namespace ICS binder.SetAttribute( "number", ToString((*it)->getNumber()).c_str() ); - Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction; + Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction; if(direction == Channel/*::ChannelDirection*/::DIRECT) { binder.SetAttribute( "direction", "DIRECT" ); - } + } else { binder.SetAttribute( "direction", "INVERSE" ); } - + float percentage = (*it)->getAttachedControlBinding(*o).percentage; binder.SetAttribute( "percentage", ToString(percentage).c_str() ); - + control.InsertEndChild(binder); } @@ -734,7 +649,7 @@ namespace ICS } } - //! @todo Future versions should consider channel exponentials and mixtures, so + //! @todo Future versions should consider channel exponentials and mixtures, so // after updating Controls, Channels should be updated according to their values } @@ -748,24 +663,6 @@ namespace ICS return mControls[i]->getValue(); } - void InputControlSystem::addJoystick(int deviceId) - { - ICS_LOG("Adding joystick (device id: " + ToString(deviceId) + ")"); - - for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++) - { - if(mControlsJoystickAxisBinderMap[deviceId].find(j) == mControlsJoystickAxisBinderMap[deviceId].end()) - { - ControlAxisBinderItem controlJoystickBinderItem; - controlJoystickBinderItem.direction = Control::STOP; - controlJoystickBinderItem.control = NULL; - mControlsJoystickAxisBinderMap[deviceId][j] = controlJoystickBinderItem; - } - } - - mJoystickIDList.push_back(deviceId); - } - Control* InputControlSystem::findControl(std::string name) { if(mActive) diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index 6a6a6bf09c..51b701b48c 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -32,7 +32,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ICSControl.h" #include "ICSChannel.h" -#include "../sdl4ogre/events.h" +#include "../sdl4ogre/events.h" + +#include "boost/lexical_cast.hpp" #define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() ); #define ICS_MAX_JOYSTICK_AXIS 16 @@ -43,16 +45,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace ICS { - class DllExport InputControlSystemLog + class DllExport InputControlSystemLog { public: virtual void logMessage(const char* text) = 0; }; - class DllExport InputControlSystem : + class DllExport InputControlSystem : public SFO::MouseListener, public SFO::KeyListener, - public SFO::JoyListener + public SFO::ControllerListener { public: @@ -62,6 +64,7 @@ namespace ICS typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions + typedef std::map JoystickInstanceMap; typedef std::list JoystickIDList; typedef struct @@ -72,7 +75,7 @@ namespace ICS InputControlSystem(std::string file = "", bool active = true , DetectingBindingListener* detectingBindingListener = NULL - , InputControlSystemLog* log = NULL, size_t channelCount = 16); + , InputControlSystemLog* log = NULL, size_t channelCount = 16); ~InputControlSystem(); std::string getFileName(){ return mFileName; }; @@ -98,50 +101,43 @@ namespace ICS inline void activate(){ this->mActive = true; }; inline void deactivate(){ this->mActive = false; }; - void addJoystick(int deviceId); - JoystickIDList& getJoystickIdList(){ return mJoystickIDList; }; - + void controllerAdded (int deviceID, const SDL_ControllerDeviceEvent &args); + void controllerRemoved(const SDL_ControllerDeviceEvent &args); + JoystickIDList& getJoystickIdList(){ return mJoystickIDList; }; + JoystickInstanceMap& getJoystickInstanceMap(){ return mJoystickInstanceMap; }; + // MouseListener void mouseMoved(const SFO::MouseMotionEvent &evt); void mousePressed(const SDL_MouseButtonEvent &evt, Uint8); void mouseReleased(const SDL_MouseButtonEvent &evt, Uint8); - + // KeyListener void keyPressed(const SDL_KeyboardEvent &evt); void keyReleased(const SDL_KeyboardEvent &evt); - - // JoyStickListener - void buttonPressed(const SDL_JoyButtonEvent &evt, int button); - void buttonReleased(const SDL_JoyButtonEvent &evt, int button); - void axisMoved(const SDL_JoyAxisEvent &evt, int axis); - void povMoved(const SDL_JoyHatEvent &evt, int index); - //TODO: does this have an SDL equivalent? - //bool sliderMoved(const OIS::JoyStickEvent &evt, int index); + + // ControllerListener + void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt); + void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt); + void axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt); void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction); bool isKeyBound(SDL_Scancode key) const; void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction); void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction); bool isMouseButtonBound(unsigned int button) const; - void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction); - void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction); - void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction); - void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction); + void addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction); + void addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction); void removeKeyBinding(SDL_Scancode key); void removeMouseAxisBinding(NamedAxis axis); void removeMouseButtonBinding(unsigned int button); - void removeJoystickAxisBinding(int deviceId, int axis); - void removeJoystickButtonBinding(int deviceId, unsigned int button); - void removeJoystickPOVBinding(int deviceId, int index, POVAxis axis); - void removeJoystickSliderBinding(int deviceId, int index); + void removeJoystickAxisBinding(int deviceID, int axis); + void removeJoystickButtonBinding(int deviceID, unsigned int button); SDL_Scancode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction); NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction); unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction); - int getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); - unsigned int getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); - POVBindingPair getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); - int getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); + int getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction); + unsigned int getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction); std::string scancodeToString(SDL_Scancode key); @@ -189,21 +185,15 @@ namespace ICS typedef std::map ControlsKeyBinderMapType; // typedef std::map ControlsAxisBinderMapType; // - typedef std::map ControlsButtonBinderMapType; // - typedef std::map ControlsPOVBinderMapType; // - typedef std::map ControlsSliderBinderMapType; // - - typedef std::map JoystickAxisBinderMapType; // > - typedef std::map JoystickButtonBinderMapType; // > - typedef std::map > JoystickPOVBinderMapType; // > > - typedef std::map JoystickSliderBinderMapType; // > + typedef std::map ControlsButtonBinderMapType; // + + typedef std::map JoystickAxisBinderMapType; // > + typedef std::map JoystickButtonBinderMapType; // > ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // - JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // > - JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // > - JoystickPOVBinderMapType mControlsJoystickPOVBinderMap; // > > - JoystickSliderBinderMapType mControlsJoystickSliderBinderMap; // > + JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // + JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // std::vector mControls; std::vector mChannels; @@ -212,7 +202,7 @@ namespace ICS bool mActive; InputControlSystemLog* mLog; - + DetectingBindingListener* mDetectingBindingListener; Control* mDetectingBindingControl; Control::ControlChangingDirection mDetectingBindingDirection; @@ -220,7 +210,8 @@ namespace ICS bool mXmouseAxisBinded; bool mYmouseAxisBinded; - JoystickIDList mJoystickIDList; + JoystickIDList mJoystickIDList; + JoystickInstanceMap mJoystickInstanceMap; int mMouseAxisBindingInitialValues[3]; @@ -242,17 +233,12 @@ namespace ICS virtual void mouseButtonBindingDetected(InputControlSystem* ICS, Control* control , unsigned int button, Control::ControlChangingDirection direction); - virtual void joystickAxisBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int axis, Control::ControlChangingDirection direction); + virtual void joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control + , int axis, Control::ControlChangingDirection direction); - virtual void joystickButtonBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, unsigned int button, Control::ControlChangingDirection direction); + virtual void joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control + , unsigned int button, Control::ControlChangingDirection direction); - virtual void joystickPOVBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction); - - virtual void joystickSliderBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int slider, Control::ControlChangingDirection direction); }; static const float ICS_MAX = std::numeric_limits::max(); diff --git a/extern/oics/ICSInputControlSystem_joystick.cpp b/extern/oics/ICSInputControlSystem_joystick.cpp index 0fcd36bbd4..ab219d0745 100644 --- a/extern/oics/ICSInputControlSystem_joystick.cpp +++ b/extern/oics/ICSInputControlSystem_joystick.cpp @@ -27,14 +27,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ICSInputControlSystem.h" #define SDL_JOY_AXIS_MIN -32768 -#define SDL_JOY_AXIS_MAX 32767 +#define SDL_JOY_AXIS_MAX 32767 +#define DEADZONE 0.1f namespace ICS { // load xml void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode) { - TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder"); + TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder"); while(xmlJoystickBinder) { Control::ControlChangingDirection dir = Control::STOP; @@ -47,8 +48,7 @@ namespace ICS dir = Control::DECREASE; } - addJoystickAxisBinding(mControls.back(), FromString(xmlJoystickBinder->Attribute("deviceId")) - , FromString(xmlJoystickBinder->Attribute("axis")), dir); + addJoystickAxisBinding(mControls.back(), FromString(xmlJoystickBinder->Attribute("deviceId")), FromString(xmlJoystickBinder->Attribute("axis")), dir); xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder"); } @@ -56,7 +56,7 @@ namespace ICS void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode) { - TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder"); + TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder"); while(xmlJoystickButtonBinder) { Control::ControlChangingDirection dir = Control::STOP; @@ -69,335 +69,194 @@ namespace ICS dir = Control::DECREASE; } - addJoystickButtonBinding(mControls.back(), FromString(xmlJoystickButtonBinder->Attribute("deviceId")) - , FromString(xmlJoystickButtonBinder->Attribute("button")), dir); + addJoystickButtonBinding(mControls.back(), FromString(xmlJoystickButtonBinder->Attribute("deviceId")), FromString(xmlJoystickButtonBinder->Attribute("button")), dir); xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder"); } } - void InputControlSystem::loadJoystickPOVBinders(TiXmlElement* xmlControlNode) - { - TiXmlElement* xmlJoystickPOVBinder = xmlControlNode->FirstChildElement("JoystickPOVBinder"); - while(xmlJoystickPOVBinder) - { - Control::ControlChangingDirection dir = Control::STOP; - if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "INCREASE") - { - dir = Control::INCREASE; - } - else if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "DECREASE") - { - dir = Control::DECREASE; - } - - InputControlSystem::POVAxis axis = /*POVAxis::*/NorthSouth; - if(std::string(xmlJoystickPOVBinder->Attribute("axis")) == "EastWest") - { - axis = /*POVAxis::*/EastWest; - } - - addJoystickPOVBinding(mControls.back(), FromString(xmlJoystickPOVBinder->Attribute("deviceId")) - , FromString(xmlJoystickPOVBinder->Attribute("pov")), axis, dir); - - xmlJoystickPOVBinder = xmlJoystickPOVBinder->NextSiblingElement("JoystickPOVBinder"); - } - } - - void InputControlSystem::loadJoystickSliderBinders(TiXmlElement* xmlControlNode) - { - TiXmlElement* xmlJoystickSliderBinder = xmlControlNode->FirstChildElement("JoystickSliderBinder"); - while(xmlJoystickSliderBinder) - { - Control::ControlChangingDirection dir = Control::STOP; - if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "INCREASE") - { - dir = Control::INCREASE; - } - else if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "DECREASE") - { - dir = Control::DECREASE; - } - - addJoystickSliderBinding(mControls.back(), FromString(xmlJoystickSliderBinder->Attribute("deviceId")) - , FromString(xmlJoystickSliderBinder->Attribute("slider")), dir); - - xmlJoystickSliderBinder = xmlJoystickSliderBinder->NextSiblingElement("JoystickSliderBinder"); - } - } - // add bindings - void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction) + void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceID, int axis, Control::ControlChangingDirection direction) { - ICS_LOG("\tAdding AxisBinder [deviceid=" - + ToString(deviceId) + ", axis=" - + ToString(axis) + ", direction=" - + ToString(direction) + "]"); + ICS_LOG("\tAdding AxisBinder [axis=" + + ToString(axis) + ", deviceID=" + + ToString(deviceID) + ", direction=" + + ToString(direction) + "]"); + + control->setValue(0.5f); //all joystick axis start at .5, so do that ControlAxisBinderItem controlAxisBinderItem; controlAxisBinderItem.control = control; controlAxisBinderItem.direction = direction; - mControlsJoystickAxisBinderMap[ deviceId ][ axis ] = controlAxisBinderItem; + mControlsJoystickAxisBinderMap[deviceID][axis] = controlAxisBinderItem; } - void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction) + void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceID, unsigned int button, Control::ControlChangingDirection direction) { - ICS_LOG("\tAdding JoystickButtonBinder [deviceId=" - + ToString(deviceId) + ", button=" - + ToString(button) + ", direction=" - + ToString(direction) + "]"); + ICS_LOG("\tAdding JoystickButtonBinder [button=" + + ToString(button) + ", deviceID=" + + ToString(deviceID) + ", direction=" + + ToString(direction) + "]"); ControlButtonBinderItem controlJoystickButtonBinderItem; controlJoystickButtonBinderItem.direction = direction; controlJoystickButtonBinderItem.control = control; - mControlsJoystickButtonBinderMap[ deviceId ][ button ] = controlJoystickButtonBinderItem; - } - - void InputControlSystem::addJoystickPOVBinding(Control* control, int deviceId, int index, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction) - { - ICS_LOG("\tAdding JoystickPOVBinder [deviceId=" - + ToString(deviceId) + ", pov=" - + ToString(index) + ", axis=" - + ToString(axis) + ", direction=" - + ToString(direction) + "]"); - - ControlPOVBinderItem ControlPOVBinderItem; - ControlPOVBinderItem.direction = direction; - ControlPOVBinderItem.control = control; - mControlsJoystickPOVBinderMap[ deviceId ][ index ][ axis ] = ControlPOVBinderItem; - } - - void InputControlSystem::addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction) - { - ICS_LOG("\tAdding JoystickSliderBinder [deviceId=" - + ToString(deviceId) + ", direction=" - + ToString(index) + ", direction=" - + ToString(direction) + "]"); - - ControlSliderBinderItem ControlSliderBinderItem; - ControlSliderBinderItem.direction = direction; - ControlSliderBinderItem.control = control; - mControlsJoystickSliderBinderMap[ deviceId ][ index ] = ControlSliderBinderItem; + mControlsJoystickButtonBinderMap[deviceID][button] = controlJoystickButtonBinderItem; } // get bindings - int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) - { - if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) + int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction) + { + if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end()) { - ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].begin(); - while(it != mControlsJoystickAxisBinderMap[deviceId].end()) - { - if(it->first >= 0 && it->second.control == control && it->second.direction == direction) - { - return it->first; - } + ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].begin(); + while(it != mControlsJoystickAxisBinderMap[deviceID].end()) + { + if(it->first >= 0 && it->second.control == control && it->second.direction == direction) + { + return it->first; + } ++it; - } - } + } + } return /*NamedAxis::*/UNASSIGNED; } - unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) - { - if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) + unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceID, ICS::Control::ControlChangingDirection direction) + { + if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end()) { - ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].begin(); - while(it != mControlsJoystickButtonBinderMap[deviceId].end()) - { - if(it->second.control == control && it->second.direction == direction) - { - return it->first; - } + ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].begin(); + while(it != mControlsJoystickButtonBinderMap[deviceID].end()) + { + if(it->second.control == control && it->second.direction == direction) + { + return it->first; + } ++it; - } - } + } + } return ICS_MAX_DEVICE_BUTTONS; } - InputControlSystem::POVBindingPair InputControlSystem::getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) - { - POVBindingPair result; - result.index = -1; - - if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end()) - { - //ControlsAxisBinderMapType::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin(); - std::map::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin(); - while(it != mControlsJoystickPOVBinderMap[deviceId].end()) - { - ControlsPOVBinderMapType::const_iterator it2 = it->second.begin(); - while(it2 != it->second.end()) - { - if(it2->second.control == control && it2->second.direction == direction) - { - result.index = it->first; - result.axis = (POVAxis)it2->first; - return result; - } - it2++; - } - - it++; - } - } - - return result; - } - - int InputControlSystem::getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) - { - if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end()) - { - ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].begin(); - while(it != mControlsJoystickSliderBinderMap[deviceId].end()) - { - if(it->second.control == control && it->second.direction == direction) - { - return it->first; - } - it++; - } - } - - return /*NamedAxis::*/UNASSIGNED; - } - // remove bindings - void InputControlSystem::removeJoystickAxisBinding(int deviceId, int axis) - { - if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) + void InputControlSystem::removeJoystickAxisBinding(int deviceID, int axis) + { + if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end()) { - ControlsButtonBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].find(axis); - if(it != mControlsJoystickAxisBinderMap[deviceId].end()) - { - mControlsJoystickAxisBinderMap[deviceId].erase(it); - } - } + ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceID].find(axis); + if(it != mControlsJoystickAxisBinderMap[deviceID].end()) + { + mControlsJoystickAxisBinderMap[deviceID].erase(it); + } + } } - void InputControlSystem::removeJoystickButtonBinding(int deviceId, unsigned int button) - { - if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) + void InputControlSystem::removeJoystickButtonBinding(int deviceID, unsigned int button) + { + if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end()) { - ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].find(button); - if(it != mControlsJoystickButtonBinderMap[deviceId].end()) - { - mControlsJoystickButtonBinderMap[deviceId].erase(it); - } - } - } - - void InputControlSystem::removeJoystickPOVBinding(int deviceId, int index, POVAxis axis) - { - if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end()) - { - std::map::iterator it = mControlsJoystickPOVBinderMap[deviceId].find(index); - if(it != mControlsJoystickPOVBinderMap[deviceId].end()) - { - if(it->second.find(axis) != it->second.end()) - { - it->second.erase( it->second.find(axis) ); - } - } - } - } - - void InputControlSystem::removeJoystickSliderBinding(int deviceId, int index) - { - if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end()) - { - ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].find(index); - if(it != mControlsJoystickSliderBinderMap[deviceId].end()) - { - mControlsJoystickSliderBinderMap[deviceId].erase(it); - } - } + ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceID].find(button); + if(it != mControlsJoystickButtonBinderMap[deviceID].end()) + { + mControlsJoystickButtonBinderMap[deviceID].erase(it); + } + } } // joyStick listeners - void InputControlSystem::buttonPressed(const SDL_JoyButtonEvent &evt, int button) - { - if(mActive) - { - if(!mDetectingBindingControl) - { - if(mControlsJoystickButtonBinderMap.find(evt.which) != mControlsJoystickButtonBinderMap.end()) - { - ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.which].find(button); - if(it != mControlsJoystickButtonBinderMap[evt.which].end()) - { - it->second.control->setIgnoreAutoReverse(false); - if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) - { - it->second.control->setChangingDirection(it->second.direction); - } - else - { - if(it->second.control->getValue() == 1) - { - it->second.control->setChangingDirection(Control::DECREASE); - } - else if(it->second.control->getValue() == 0) - { - it->second.control->setChangingDirection(Control::INCREASE); - } - } - } - } - } - else if(mDetectingBindingListener) - { - mDetectingBindingListener->joystickButtonBindingDetected(this, - mDetectingBindingControl, evt.which, button, mDetectingBindingDirection); - } - } - } - - void InputControlSystem::buttonReleased(const SDL_JoyButtonEvent &evt, int button) - { - if(mActive) - { - if(mControlsJoystickButtonBinderMap.find(evt.which) != mControlsJoystickButtonBinderMap.end()) - { - ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.which].find(button); - if(it != mControlsJoystickButtonBinderMap[evt.which].end()) - { - it->second.control->setChangingDirection(Control::STOP); - } - } - } - } - - void InputControlSystem::axisMoved(const SDL_JoyAxisEvent &evt, int axis) + void InputControlSystem::buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt) { if(mActive) { if(!mDetectingBindingControl) + { + if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button); + if(it != mControlsJoystickButtonBinderMap[deviceID].end()) + { + it->second.control->setIgnoreAutoReverse(false); + if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) + { + it->second.control->setChangingDirection(it->second.direction); + } + else + { + if(it->second.control->getValue() == 1) + { + it->second.control->setChangingDirection(Control::DECREASE); + } + else if(it->second.control->getValue() == 0) + { + it->second.control->setChangingDirection(Control::INCREASE); + } + } + } + } + } + } + } + + void InputControlSystem::buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickButtonBinderMap.find(deviceID) != mControlsJoystickButtonBinderMap.end()) + { + ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[deviceID].find(evt.button); + if(it != mControlsJoystickButtonBinderMap[deviceID].end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + } + else if(mDetectingBindingListener) { - if(mControlsJoystickAxisBinderMap.find(evt.which) != mControlsJoystickAxisBinderMap.end()) - { - ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.which ][ axis ]; // joystic axis start at 0 index - Control* ctrl = joystickBinderItem.control; - if(ctrl) - { - ctrl->setIgnoreAutoReverse(true); + mDetectingBindingListener->joystickButtonBindingDetected(this, deviceID, + mDetectingBindingControl, evt.button, mDetectingBindingDirection); + } + } + } - float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN; - float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN); + void InputControlSystem::axisMoved(int deviceID, const SDL_ControllerAxisEvent &evt) + { + if(mActive) + { + if(!mDetectingBindingControl) + { + if(mControlsJoystickAxisBinderMap.find(deviceID) != mControlsJoystickAxisBinderMap.end()) + { + ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[deviceID][evt.axis]; // joystic axis start at 0 index + Control* ctrl = joystickBinderItem.control; + if(ctrl) + { + ctrl->setIgnoreAutoReverse(true); - if(joystickBinderItem.direction == Control::INCREASE) - { - ctrl->setValue( valDisplaced / axisRange ); - } - else if(joystickBinderItem.direction == Control::DECREASE) - { - ctrl->setValue( 1 - ( valDisplaced / axisRange ) ); - } - } - } + float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN; + float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN); + float percent = valDisplaced / axisRange * (1+DEADZONE*2) - DEADZONE; //Assures all values, 0 through 1, are seen + if(percent > .5-DEADZONE && percent < .5+DEADZONE) //close enough to center + percent = .5; + else if(percent > .5) + percent -= DEADZONE; + else + percent += DEADZONE; + + if(joystickBinderItem.direction == Control::INCREASE) + { + ctrl->setValue( percent ); + } + else if(joystickBinderItem.direction == Control::DECREASE) + { + ctrl->setValue( 1 - ( percent ) ); + } + } + } } else if(mDetectingBindingListener) { @@ -408,250 +267,76 @@ namespace ICS { if( abs( evt.value ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN) { - mDetectingBindingListener->joystickAxisBindingDetected(this, - mDetectingBindingControl, evt.which, axis, mDetectingBindingDirection); + mDetectingBindingListener->joystickAxisBindingDetected(this, deviceID, + mDetectingBindingControl, evt.axis, mDetectingBindingDirection); } } } } - } - - //Here be dragons, apparently - void InputControlSystem::povMoved(const SDL_JoyHatEvent &evt, int index) + } + + void InputControlSystem::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &args) { - if(mActive) - { - if(!mDetectingBindingControl) - { - if(mControlsJoystickPOVBinderMap.find(evt.which) != mControlsJoystickPOVBinderMap.end()) - { - std::map::const_iterator i = mControlsJoystickPOVBinderMap[ evt.which ].find(index); - if(i != mControlsJoystickPOVBinderMap[ evt.which ].end()) - { - if(evt.value != SDL_HAT_LEFT - && evt.value != SDL_HAT_RIGHT - && evt.value != SDL_HAT_CENTERED) - { - ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth ); - if(it != i->second.end()) - { - it->second.control->setIgnoreAutoReverse(false); - if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) - { - if(evt.value == SDL_HAT_UP - || evt.value == SDL_HAT_LEFTUP - || evt.value == SDL_HAT_RIGHTUP) - { - it->second.control->setChangingDirection(it->second.direction); - } - else - { - it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction)); - } - } - else - { - if(it->second.control->getValue() == 1) - { - it->second.control->setChangingDirection(Control::DECREASE); - } - else if(it->second.control->getValue() == 0) - { - it->second.control->setChangingDirection(Control::INCREASE); - } - } - } - } + ICS_LOG("Adding joystick (index: " + ToString(args.which) + ")"); + SDL_GameController* cntrl = SDL_GameControllerOpen(args.which); + int instanceID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(cntrl)); + if(std::find(mJoystickIDList.begin(), mJoystickIDList.end(), deviceID)==mJoystickIDList.end()) + { + for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++) + { + if(mControlsJoystickAxisBinderMap[deviceID].find(j) == mControlsJoystickAxisBinderMap[deviceID].end()) + { + ControlAxisBinderItem controlJoystickBinderItem; + controlJoystickBinderItem.direction = Control::STOP; + controlJoystickBinderItem.control = NULL; + mControlsJoystickAxisBinderMap[deviceID][j] = controlJoystickBinderItem; + } + } + mJoystickIDList.push_front(deviceID); + } - if(evt.value != SDL_HAT_UP - && evt.value != SDL_HAT_DOWN - && evt.value != SDL_HAT_CENTERED) - { - ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/EastWest ); - if(it != i->second.end()) - { - it->second.control->setIgnoreAutoReverse(false); - if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) - { - if(evt.value == SDL_HAT_RIGHT - || evt.value == SDL_HAT_RIGHTUP - || evt.value == SDL_HAT_RIGHTDOWN) - { - it->second.control->setChangingDirection(it->second.direction); - } - else - { - it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction)); - } - } - else - { - if(it->second.control->getValue() == 1) - { - it->second.control->setChangingDirection(Control::DECREASE); - } - else if(it->second.control->getValue() == 0) - { - it->second.control->setChangingDirection(Control::INCREASE); - } - } - } - } - - if(evt.value == SDL_HAT_CENTERED) - { - ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth ); - if(it != i->second.end()) - { - it->second.control->setChangingDirection(Control::STOP); - } - - it = i->second.find( /*POVAxis::*/EastWest ); - if(it != i->second.end()) - { - it->second.control->setChangingDirection(Control::STOP); - } - } - } - } - } - else if(mDetectingBindingListener) - { - if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable()) - { - if(evt.value == SDL_HAT_LEFT - || evt.value == SDL_HAT_RIGHT - || evt.value == SDL_HAT_UP - || evt.value == SDL_HAT_DOWN) - { - POVAxis povAxis = NorthSouth; - if(evt.value == SDL_HAT_LEFT - || evt.value == SDL_HAT_RIGHT) - { - povAxis = EastWest; - } - - mDetectingBindingListener->joystickPOVBindingDetected(this, - mDetectingBindingControl, evt.which, index, povAxis, mDetectingBindingDirection); - } - } - } - } + mJoystickInstanceMap[instanceID] = cntrl; + } + void InputControlSystem::controllerRemoved(const SDL_ControllerDeviceEvent &args) + { + ICS_LOG("Removing joystick (instance id: " + ToString(args.which) + ")"); + if(mJoystickInstanceMap.count(args.which)!=0) + { + SDL_GameControllerClose(mJoystickInstanceMap.at(args.which)); + mJoystickInstanceMap.erase(args.which); + } } - //TODO: does this have an SDL equivalent? - /* - void InputControlSystem::sliderMoved(const OIS::JoyStickEvent &evt, int index) - { - if(mActive) - { - if(!mDetectingBindingControl) - { - if(mControlsJoystickSliderBinderMap.find(evt.device->getID()) != mControlsJoystickSliderBinderMap.end()) - { - ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ]; - Control* ctrl = joystickBinderItem.control; - if(ctrl) - { - ctrl->setIgnoreAutoReverse(true); - if(joystickBinderItem.direction == Control::INCREASE) - { - float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; - float valDisplaced = (float)( evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS); - - ctrl->setValue( valDisplaced / axisRange ); - } - else if(joystickBinderItem.direction == Control::DECREASE) - { - float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS; - float valDisplaced = (float)(evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS); - - ctrl->setValue( 1 - ( valDisplaced / axisRange ) ); - } - } - } - } - else if(mDetectingBindingListener) - { - if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable()) - { - if( abs( evt.state.mSliders[index].abX ) > ICS_JOYSTICK_SLIDER_BINDING_MARGIN) - { - mDetectingBindingListener->joystickSliderBindingDetected(this, - mDetectingBindingControl, evt.device->getID(), index, mDetectingBindingDirection); - } - } - } - } - } - */ - // joystick auto bindings - void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int axis, Control::ControlChangingDirection direction) + void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, int deviceID, Control* control, int axis, Control::ControlChangingDirection direction) { // if the joystick axis is used by another control, remove it - ICS->removeJoystickAxisBinding(deviceId, axis); + ICS->removeJoystickAxisBinding(deviceID, axis); // if the control has an axis assigned, remove it - int oldAxis = ICS->getJoystickAxisBinding(control, deviceId, direction); - if(oldAxis != InputControlSystem::UNASSIGNED) + int oldAxis = ICS->getJoystickAxisBinding(control, deviceID, direction); + if(oldAxis != InputControlSystem::UNASSIGNED) { - ICS->removeJoystickAxisBinding(deviceId, oldAxis); + ICS->removeJoystickAxisBinding(deviceID, oldAxis); } - ICS->addJoystickAxisBinding(control, deviceId, axis, direction); + ICS->addJoystickAxisBinding(control, deviceID, axis, direction); ICS->cancelDetectingBindingState(); } - void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, unsigned int button, Control::ControlChangingDirection direction) + void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, int deviceID, Control* control + , unsigned int button, Control::ControlChangingDirection direction) { // if the joystick button is used by another control, remove it - ICS->removeJoystickButtonBinding(deviceId, button); + ICS->removeJoystickButtonBinding(deviceID, button); // if the control has a joystick button assigned, remove it - unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceId, direction); + unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceID, direction); if(oldButton != ICS_MAX_DEVICE_BUTTONS) { - ICS->removeJoystickButtonBinding(deviceId, oldButton); + ICS->removeJoystickButtonBinding(deviceID, oldButton); } - ICS->addJoystickButtonBinding(control, deviceId, button, direction); - ICS->cancelDetectingBindingState(); - } - - - void DetectingBindingListener::joystickPOVBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction) - { - // if the joystick slider is used by another control, remove it - ICS->removeJoystickPOVBinding(deviceId, pov, axis); - - // if the control has a joystick button assigned, remove it - ICS::InputControlSystem::POVBindingPair oldPOV = ICS->getJoystickPOVBinding(control, deviceId, direction); - if(oldPOV.index >= 0 && oldPOV.axis == axis) - { - ICS->removeJoystickPOVBinding(deviceId, oldPOV.index, oldPOV.axis); - } - - ICS->addJoystickPOVBinding(control, deviceId, pov, axis, direction); - ICS->cancelDetectingBindingState(); - } - - void DetectingBindingListener::joystickSliderBindingDetected(InputControlSystem* ICS, Control* control - , int deviceId, int slider, Control::ControlChangingDirection direction) - { - // if the joystick slider is used by another control, remove it - ICS->removeJoystickSliderBinding(deviceId, slider); - - // if the control has a joystick slider assigned, remove it - int oldSlider = ICS->getJoystickSliderBinding(control, deviceId, direction); - if(oldSlider != InputControlSystem::/*NamedAxis::*/UNASSIGNED) - { - ICS->removeJoystickSliderBinding(deviceId, oldSlider); - } - - ICS->addJoystickSliderBinding(control, deviceId, slider, direction); + ICS->addJoystickButtonBinding(control, deviceID, button, direction); ICS->cancelDetectingBindingState(); } } diff --git a/extern/sdl4ogre/CMakeLists.txt b/extern/sdl4ogre/CMakeLists.txt index 86ce7b70ed..b8c56bd000 100644 --- a/extern/sdl4ogre/CMakeLists.txt +++ b/extern/sdl4ogre/CMakeLists.txt @@ -6,6 +6,7 @@ set(SDL4OGRE_SOURCE_FILES sdlinputwrapper.cpp sdlcursormanager.cpp sdlwindowhelper.cpp + imagerotate.cpp ) if (APPLE) diff --git a/extern/sdl4ogre/events.h b/extern/sdl4ogre/events.h index 6961e81fc8..986dd7d8b5 100644 --- a/extern/sdl4ogre/events.h +++ b/extern/sdl4ogre/events.h @@ -40,23 +40,25 @@ public: virtual void keyReleased(const SDL_KeyboardEvent &arg) = 0; }; -class JoyListener +class ControllerListener { public: - virtual ~JoyListener() {} + virtual ~ControllerListener() {} /** @remarks Joystick button down event */ - virtual void buttonPressed( const SDL_JoyButtonEvent &evt, int button ) = 0; + virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &evt) = 0; /** @remarks Joystick button up event */ - virtual void buttonReleased( const SDL_JoyButtonEvent &evt, int button ) = 0; + virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &evt) = 0; /** @remarks Joystick axis moved event */ - virtual void axisMoved( const SDL_JoyAxisEvent &arg, int axis ) = 0; + virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg) = 0; - //-- Not so common control events, so are not required --// + /** @remarks Joystick Added **/ + virtual void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg) = 0; + + /** @remarks Joystick Removed **/ + virtual void controllerRemoved(const SDL_ControllerDeviceEvent &arg) = 0; - //! Joystick Event, and povID - virtual void povMoved( const SDL_JoyHatEvent &arg, int index) {} }; class WindowListener diff --git a/libs/openengine/ogre/imagerotate.cpp b/extern/sdl4ogre/imagerotate.cpp similarity index 99% rename from libs/openengine/ogre/imagerotate.cpp rename to extern/sdl4ogre/imagerotate.cpp index cc5f572cf9..b825943fc1 100644 --- a/libs/openengine/ogre/imagerotate.cpp +++ b/extern/sdl4ogre/imagerotate.cpp @@ -17,7 +17,9 @@ #include using namespace Ogre; -using namespace OEngine::Render; + +namespace SFO +{ void ImageRotate::rotate(const std::string& sourceImage, const std::string& destImage, const float angle) { @@ -93,3 +95,5 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest root->destroySceneManager(sceneMgr); delete rect; } + +} diff --git a/libs/openengine/ogre/imagerotate.hpp b/extern/sdl4ogre/imagerotate.hpp similarity index 94% rename from libs/openengine/ogre/imagerotate.hpp rename to extern/sdl4ogre/imagerotate.hpp index a3f6d662f3..7135a571ab 100644 --- a/libs/openengine/ogre/imagerotate.hpp +++ b/extern/sdl4ogre/imagerotate.hpp @@ -3,9 +3,8 @@ #include -namespace OEngine -{ -namespace Render + +namespace SFO { /// Rotate an image by certain degrees and save as file, uses the GPU @@ -22,6 +21,5 @@ namespace Render }; } -} #endif diff --git a/extern/sdl4ogre/sdlcursormanager.cpp b/extern/sdl4ogre/sdlcursormanager.cpp index 7623d57dbf..61d9c32dd6 100644 --- a/extern/sdl4ogre/sdlcursormanager.cpp +++ b/extern/sdl4ogre/sdlcursormanager.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include "imagerotate.hpp" namespace SFO { @@ -91,7 +91,7 @@ namespace SFO // we use a render target to uncompress the DDS texture // just blitting doesn't seem to work on D3D9 - OEngine::Render::ImageRotate::rotate(tex->getName(), tempName, -rotDegrees); + ImageRotate::rotate(tex->getName(), tempName, static_cast(-rotDegrees)); Ogre::TexturePtr resultTexture = Ogre::TextureManager::getSingleton().getByName(tempName); @@ -110,7 +110,8 @@ namespace SFO Ogre::ColourValue clr = destImage.getColourAt(x, y, 0); //set the pixel on the SDL surface to the same value as the Ogre texture's - _putPixel(surf, x, y, SDL_MapRGBA(surf->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255)); + _putPixel(surf, x, y, SDL_MapRGBA(surf->format, static_cast(clr.r * 255), + static_cast(clr.g * 255), static_cast(clr.b * 255), static_cast(clr.a * 255))); } } diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index a6c7d3e5ca..aaf669ff43 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -20,7 +20,7 @@ namespace SFO mMouseY(0), mMouseX(0), mMouseInWindow(true), - mJoyListener(NULL), + mConListener(NULL), mKeyboardListener(NULL), mMouseListener(NULL), mWindowListener(NULL), @@ -91,24 +91,32 @@ namespace SFO case SDL_TEXTINPUT: mKeyboardListener->textInput(evt.text); break; + case SDL_JOYHATMOTION: //As we manage everything with GameController, don't even bother with these. case SDL_JOYAXISMOTION: - if (mJoyListener) - mJoyListener->axisMoved(evt.jaxis, evt.jaxis.axis); - break; case SDL_JOYBUTTONDOWN: - if (mJoyListener) - mJoyListener->buttonPressed(evt.jbutton, evt.jbutton.button); - break; case SDL_JOYBUTTONUP: - if (mJoyListener) - mJoyListener->buttonReleased(evt.jbutton, evt.jbutton.button); - break; case SDL_JOYDEVICEADDED: - //SDL_JoystickOpen(evt.jdevice.which); - //std::cout << "Detected a new joystick: " << SDL_JoystickNameForIndex(evt.jdevice.which) << std::endl; - break; case SDL_JOYDEVICEREMOVED: - //std::cout << "A joystick has been removed" << std::endl; + break; + case SDL_CONTROLLERDEVICEADDED: + if(mConListener) + mConListener->controllerAdded(1, evt.cdevice); //We only support one joystick, so give everything a generic deviceID + break; + case SDL_CONTROLLERDEVICEREMOVED: + if(mConListener) + mConListener->controllerRemoved(evt.cdevice); + break; + case SDL_CONTROLLERBUTTONDOWN: + if(mConListener) + mConListener->buttonPressed(1, evt.cbutton); + break; + case SDL_CONTROLLERBUTTONUP: + if(mConListener) + mConListener->buttonReleased(1, evt.cbutton); + break; + case SDL_CONTROLLERAXISMOTION: + if(mConListener) + mConListener->axisMoved(1, evt.caxis); break; case SDL_WINDOWEVENT: handleWindowEvent(evt); @@ -193,12 +201,12 @@ namespace SFO bool InputWrapper::isModifierHeld(SDL_Keymod mod) { - return SDL_GetModState() & mod; + return (SDL_GetModState() & mod) != 0; } bool InputWrapper::isKeyDown(SDL_Scancode key) { - return SDL_GetKeyboardState(NULL)[key]; + return (SDL_GetKeyboardState(NULL)[key]) != 0; } /// \brief Moves the mouse to the specified point within the viewport diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index af16ab68d8..a7023207c6 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -24,7 +24,7 @@ namespace SFO void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; } void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; } void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; } - void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; } + void setControllerEventCallback(ControllerListener* listen) { mConListener = listen; } void capture(bool windowEventsOnly); bool isModifierHeld(SDL_Keymod mod); @@ -54,7 +54,7 @@ namespace SFO SFO::MouseListener* mMouseListener; SFO::KeyListener* mKeyboardListener; SFO::WindowListener* mWindowListener; - SFO::JoyListener* mJoyListener; + SFO::ControllerListener* mConListener; typedef boost::unordered_map KeyMap; KeyMap mKeyMap; diff --git a/extern/sdl4ogre/sdlwindowhelper.cpp b/extern/sdl4ogre/sdlwindowhelper.cpp index 44993947f6..637fae0efe 100644 --- a/extern/sdl4ogre/sdlwindowhelper.cpp +++ b/extern/sdl4ogre/sdlwindowhelper.cpp @@ -93,7 +93,8 @@ void SDLWindowHelper::setWindowIcon(const std::string &name) int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - Uint32 pixel = SDL_MapRGBA(surface->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255); + Uint32 pixel = SDL_MapRGBA(surface->format, static_cast(clr.r * 255), + static_cast(clr.g * 255), static_cast(clr.b * 255), static_cast(clr.a * 255)); switch(bpp) { case 1: *p = pixel; diff --git a/extern/shiny/Platforms/Ogre/OgrePass.cpp b/extern/shiny/Platforms/Ogre/OgrePass.cpp index 3a25c5c740..5cd501094f 100644 --- a/extern/shiny/Platforms/Ogre/OgrePass.cpp +++ b/extern/shiny/Platforms/Ogre/OgrePass.cpp @@ -109,7 +109,7 @@ namespace sh { params->addSharedParameters (name); } - catch (Ogre::Exception& e) + catch (Ogre::Exception& ) { std::stringstream msg; msg << "Could not create a shared parameter instance for '" diff --git a/files/gamecontrollerdb.txt b/files/gamecontrollerdb.txt new file mode 100644 index 0000000000..bd8d9c5fc4 --- /dev/null +++ b/files/gamecontrollerdb.txt @@ -0,0 +1,101 @@ +# from https://github.com/gabomdq/SDL_GameControllerDB +# License: +# Simple DirectMedia Layer +# Copyright (C) 1997-2013 Sam Lantinga +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# 3. This notice may not be removed or altered from any source distribution. + +# Windows - DINPUT +8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13, +4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows, +00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, +00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows, +28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, +ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9, +8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5, + +# OS X +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,Platform:Mac OS X, +5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X, +4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X, +8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, + +# Linux +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux, +03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5, +030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, +030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux, +030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3, +05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7, +0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, +0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux, +030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1, +030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4, +030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5, +030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2, +030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8tart:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4, diff --git a/files/materials/atmosphere.shader b/files/materials/atmosphere.shader index 5040052fc0..3eaa73b1ca 100644 --- a/files/materials/atmosphere.shader +++ b/files/materials/atmosphere.shader @@ -11,7 +11,7 @@ SH_START_PROGRAM { float4x4 viewFixed = view; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES viewFixed[0][3] = 0.0; viewFixed[1][3] = 0.0; viewFixed[2][3] = 0.0; diff --git a/files/materials/clouds.shader b/files/materials/clouds.shader index 93d0780e09..5902d2fdcc 100644 --- a/files/materials/clouds.shader +++ b/files/materials/clouds.shader @@ -13,7 +13,7 @@ { float4x4 worldviewFixed = worldview; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES worldviewFixed[0][3] = 0.0; worldviewFixed[1][3] = 0.0; worldviewFixed[2][3] = 0.0; diff --git a/files/materials/moon.shader b/files/materials/moon.shader index 0e1a4ffc8d..151b94180f 100644 --- a/files/materials/moon.shader +++ b/files/materials/moon.shader @@ -12,7 +12,7 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix) SH_START_PROGRAM { float4x4 viewFixed = view; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES viewFixed[0][3] = 0.0; viewFixed[1][3] = 0.0; viewFixed[2][3] = 0.0; diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 828674cc72..5c74b11393 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -166,7 +166,7 @@ #if VIEWPROJ_FIX float4x4 vpFixed = vpMatrix; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES vpFixed[2] = vpRow2Fix; #else vpFixed[0][2] = vpRow2Fix.x; @@ -384,7 +384,7 @@ float4 normalTex = shSample(normalMap, UV.xy); - normal = normalize (shMatrixMult( transpose(tbn), normalTex.xyz * 2.0 - float3 (1.0,1.0,1.0) )); + normal = normalize (shMatrixMult( transpose(tbn), normalTex.xyz * 2.0 - 1.0 )); #endif #if ENV_MAP || SPECULAR || PARALLAX diff --git a/files/materials/stars.shader b/files/materials/stars.shader index f2eb616a27..830be862a4 100644 --- a/files/materials/stars.shader +++ b/files/materials/stars.shader @@ -13,7 +13,7 @@ SH_START_PROGRAM { float4x4 worldviewFixed = worldview; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES worldviewFixed[0][3] = 0.0; worldviewFixed[1][3] = 0.0; worldviewFixed[2][3] = 0.0; diff --git a/files/materials/sun.shader b/files/materials/sun.shader index fc747b522f..72e49d1a71 100644 --- a/files/materials/sun.shader +++ b/files/materials/sun.shader @@ -12,7 +12,7 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix) SH_START_PROGRAM { float4x4 viewFixed = view; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES viewFixed[0][3] = 0.0; viewFixed[1][3] = 0.0; viewFixed[2][3] = 0.0; diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 9bb5d247da..f20fce5063 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -136,7 +136,7 @@ #if NEED_DEPTH #if VIEWPROJ_FIX float4x4 vpFixed = viewProjMatrix; -#if !SH_GLSL +#if !SH_GLSL && !SH_GLSLES vpFixed[2] = vpRow2Fix; #else vpFixed[0][2] = vpRow2Fix.x; diff --git a/files/materials/underwater.h b/files/materials/underwater.h index 332a0fd7d7..2f38f65461 100644 --- a/files/materials/underwater.h +++ b/files/materials/underwater.h @@ -93,7 +93,7 @@ float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 waterEyePos, // NOTE: the original shader calculated a tangent space basis here, // but using only the world normal is cheaper and i couldn't see a visual difference // also, if this effect gets moved to screen-space some day, it's unlikely to have tangent information - float3 causticNorm = worldNormal.xyz * perturb(causticMap, causticPos.xy, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).xyz * 2 - 1; + float3 causticNorm = worldNormal.xyz * perturb(causticMap, causticPos.xy, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).xyz * 2.0 - 1.0; causticNorm = float3(causticNorm.x, causticNorm.y, -causticNorm.z); //float fresnel = pow(clamp(dot(LV,causticnorm),0.0,1.0),2.0); @@ -111,7 +111,7 @@ float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 waterEyePos, //caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*sunFade*causticdepth; caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth,5.5*causticdepth,5.5*causticdepth)))*NdotL*causticdepth; - caustics *= 3; + caustics *= 3.0; // shore transition caustics = shLerp (float3(1,1,1), caustics, waterDepth); diff --git a/files/materials/water.shader b/files/materials/water.shader index 10d63cdf42..eff245b5ed 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -97,7 +97,7 @@ shOutputPosition = shMatrixMult(wvp, shInputPosition); - #if !SH_GLSL + #if !SH_GLSL && !SH_GLSLES float4x4 scalemat = float4x4( 0.5, 0.0, 0.0, 0.5, 0.0, -0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, diff --git a/files/mygui/openmw_hud.layout b/files/mygui/openmw_hud.layout index 8334e34b96..0cbe0dd971 100644 --- a/files/mygui/openmw_hud.layout +++ b/files/mygui/openmw_hud.layout @@ -127,35 +127,35 @@ - + - + - + - + - - + + - - + + - + diff --git a/files/mygui/openmw_loading_screen.layout b/files/mygui/openmw_loading_screen.layout index 8a1514f844..92bc5aa4c5 100644 --- a/files/mygui/openmw_loading_screen.layout +++ b/files/mygui/openmw_loading_screen.layout @@ -10,7 +10,7 @@ - + diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 4a993e1406..2efd5841ed 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -4,7 +4,7 @@ - + @@ -172,15 +172,21 @@ - + + + + + + + - + - + @@ -190,10 +196,10 @@ - + - + @@ -203,11 +209,11 @@ - + - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index fe01d3417e..e459f22fab 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -19,9 +19,11 @@ color_misc=0,205,205 # ???? - + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 19b570e2ad..de22e1b56b 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -194,6 +194,8 @@ always run = false allow third person zoom = false +toggle sneak = false + [Game] # Always use the most powerful attack when striking with a weapon (chop, slash or thrust) best attack = false diff --git a/libs/openengine/CMakeLists.txt b/libs/openengine/CMakeLists.txt new file mode 100644 index 0000000000..3542becf64 --- /dev/null +++ b/libs/openengine/CMakeLists.txt @@ -0,0 +1,38 @@ +set(OENGINE_OGRE + ogre/renderer.cpp + ogre/lights.cpp + ogre/selectionbuffer.cpp +) + +set(OENGINE_GUI + gui/loglistener.cpp + gui/manager.cpp + gui/layout.cpp +) + +set(OENGINE_BULLET + bullet/BtOgre.cpp + bullet/BtOgreExtras.h + bullet/BtOgreGP.h + bullet/BtOgrePG.h + bullet/physic.cpp + bullet/physic.hpp + bullet/BulletShapeLoader.cpp + bullet/BulletShapeLoader.h + bullet/trace.cpp + bullet/trace.h +) + +set(OENGINE_MISC + misc/rng.cpp + misc/rng.hpp +) + +set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET} ${OENGINE_MISC}) + +set(OENGINE_LIBRARY "oengine") +set(OENGINE_LIBRARY ${OENGINE_LIBRARY} PARENT_SCOPE) + +source_group(oengine FILES ${OENGINE_ALL}) + +add_library(${OENGINE_LIBRARY} STATIC ${OENGINE_ALL}) diff --git a/libs/openengine/bullet/BtOgre.cpp b/libs/openengine/bullet/BtOgre.cpp index de9ea6f57c..0af173adc2 100644 --- a/libs/openengine/bullet/BtOgre.cpp +++ b/libs/openengine/bullet/BtOgre.cpp @@ -150,7 +150,7 @@ namespace BtOgre { if (i == mBoneIndex->end()) { l = new Vector3Array; - mBoneIndex->insert(BoneKeyIndex(currBone, l)); + mBoneIndex->insert(std::make_pair(currBone, l)); } else { @@ -215,7 +215,7 @@ namespace BtOgre { if (mBoundRadius == (-1)) { getSize(); - mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5); + mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5f); } return mBoundRadius; } @@ -737,7 +737,7 @@ namespace BtOgre { { box_kCenter += vertices[c]; } - const Ogre::Real invVertexCount = 1.0 / vertex_count; + const Ogre::Real invVertexCount = 1.0f / vertex_count; box_kCenter *= invVertexCount; } Quaternion orient = boneOrientation; @@ -782,9 +782,9 @@ namespace BtOgre { box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min); box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min); - box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] + - (0.5*(fY1Max+fY1Min))*box_akAxis[1] + - (0.5*(fY2Max+fY2Min))*box_akAxis[2]; + box_kCenter += (0.5f*(fY0Max+fY0Min))*box_akAxis[0] + + (0.5f*(fY1Max+fY1Min))*box_akAxis[1] + + (0.5f*(fY2Max+fY2Min))*box_akAxis[2]; box_afExtent *= 2.0; diff --git a/libs/openengine/bullet/BtOgreGP.h b/libs/openengine/bullet/BtOgreGP.h index dde606a4f2..7e497b5352 100644 --- a/libs/openengine/bullet/BtOgreGP.h +++ b/libs/openengine/bullet/BtOgreGP.h @@ -27,7 +27,6 @@ namespace BtOgre { typedef std::map BoneIndex; -typedef std::pair BoneKeyIndex; class VertexIndexToShape { diff --git a/libs/openengine/bullet/BulletShapeLoader.cpp b/libs/openengine/bullet/BulletShapeLoader.cpp index fd9204b441..92d56b42c5 100644 --- a/libs/openengine/bullet/BulletShapeLoader.cpp +++ b/libs/openengine/bullet/BulletShapeLoader.cpp @@ -117,6 +117,13 @@ BulletShapePtr BulletShapeManager::create (const Ogre::String& name, const Ogre: return createResource(name,group,isManual,loader,createParams).staticCast(); } +Ogre::ResourcePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group, + bool isManual, Ogre::ManualResourceLoader *loader, const Ogre::NameValuePairList *loadParams, + bool backgroundThread) +{ + return this->load(name, group); +} + BulletShapePtr BulletShapeManager::load(const Ogre::String &name, const Ogre::String &group) { BulletShapePtr textf = getByName(name); diff --git a/libs/openengine/bullet/BulletShapeLoader.h b/libs/openengine/bullet/BulletShapeLoader.h index 31ee3cc7d8..907ff8bfe9 100644 --- a/libs/openengine/bullet/BulletShapeLoader.h +++ b/libs/openengine/bullet/BulletShapeLoader.h @@ -92,6 +92,11 @@ private: /** \brief Private operator= . This is a forbidden operation. */ BulletShapeManager& operator=(const BulletShapeManager &); + // Not intended to be used, declared here to keep the compiler from complaining + // about hidden virtual methods. + virtual Ogre::ResourcePtr load(const Ogre::String &name, const Ogre::String &group, + bool isManual, Ogre::ManualResourceLoader *loader, const Ogre::NameValuePairList *loadParams, + bool backgroundThread); public: @@ -101,7 +106,8 @@ public: /// Get a resource by name /// @see ResourceManager::getByName - BulletShapePtr getByName(const Ogre::String& name, const Ogre::String& groupName = Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); + BulletShapePtr getByName(const Ogre::String& name, + const Ogre::String& groupName = Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); /// Create a new shape /// @see ResourceManager::createResource diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 1ef00a0e13..013ef1003e 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -283,14 +283,14 @@ namespace Physic } } - void PhysicEngine::setDebugRenderingMode(int mode) + void PhysicEngine::setDebugRenderingMode(bool isDebug) { if(!isDebugCreated) { createDebugRendering(); } - mDebugDrawer->setDebugMode(mode); - mDebugActive = mode; + mDebugDrawer->setDebugMode(isDebug); + mDebugActive = isDebug; } bool PhysicEngine::toggleDebugRendering() @@ -385,7 +385,7 @@ namespace Physic } btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape( - sqrtVerts, sqrtVerts, heights, 1, + static_cast(sqrtVerts), static_cast(sqrtVerts), heights, 1, minh, maxh, 2, PHY_FLOAT,true); @@ -396,7 +396,7 @@ namespace Physic btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,0,hfShape); RigidBody* body = new RigidBody(CI,name); - body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); + body->getWorldTransform().setOrigin(btVector3( (x+0.5f)*triSize*(sqrtVerts-1), (y+0.5f)*triSize*(sqrtVerts-1), (maxh+minh)/2.f)); HeightField hf; hf.mBody = body; @@ -414,13 +414,17 @@ namespace Physic + boost::lexical_cast(x) + "_" + boost::lexical_cast(y); - HeightField hf = mHeightFieldMap [name]; + HeightFieldContainer::iterator it = mHeightFieldMap.find(name); + if (it == mHeightFieldMap.end()) + return; + + const HeightField& hf = it->second; mDynamicsWorld->removeRigidBody(hf.mBody); delete hf.mShape; delete hf.mBody; - mHeightFieldMap.erase(name); + mHeightFieldMap.erase(it); } void PhysicEngine::adjustRigidBody(RigidBody* body, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, @@ -716,7 +720,7 @@ namespace Physic void PhysicEngine::stepSimulation(double deltaT) { // This seems to be needed for character controller objects - mDynamicsWorld->stepSimulation(deltaT,10, 1/60.0); + mDynamicsWorld->stepSimulation(static_cast(deltaT), 10, 1 / 60.0f); if(isDebugCreated) { mDebugDrawer->step(); @@ -824,7 +828,7 @@ namespace Physic if (callback.hasHit()) return std::make_pair(true, callback.m_closestHitFraction); else - return std::make_pair(false, 1); + return std::make_pair(false, 1.0f); } std::vector< std::pair > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to, int filterGroup) diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index f497150f9c..7784e8941d 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -258,13 +258,12 @@ namespace Physic const Ogre::Vector3 &position, float scale, const Ogre::Quaternion &rotation); /** - * Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? + * Remove a character from the scene. */ void removeCharacter(const std::string &name); /** * Return a pointer to a character - * TODO:check if the actor exist... */ PhysicActor* getCharacter(const std::string &name); @@ -283,7 +282,7 @@ namespace Physic * Set the debug rendering mode. 0 to turn it off. * Important Note: this will crash if the Render is not yet initialise! */ - void setDebugRenderingMode(int mode); + void setDebugRenderingMode(bool isDebug); bool toggleDebugRendering(); diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 512c7f0698..3496478929 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -451,7 +451,6 @@ public: mRenderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA); // always use wireframe - // TODO: add option to enable wireframe mode in platform mRenderSystem->_setPolygonMode(Ogre::PM_SOLID); } diff --git a/libs/openengine/misc/rng.cpp b/libs/openengine/misc/rng.cpp new file mode 100644 index 0000000000..3d50400df0 --- /dev/null +++ b/libs/openengine/misc/rng.cpp @@ -0,0 +1,29 @@ +#include "rng.hpp" +#include +#include + +namespace OEngine { +namespace Misc { + + void Rng::init() + { + std::srand(static_cast(std::time(NULL))); + } + + float Rng::rollProbability() + { + return static_cast(std::rand() / (static_cast(RAND_MAX)+1.0)); + } + + float Rng::rollClosedProbability() + { + return static_cast(std::rand() / static_cast(RAND_MAX)); + } + + int Rng::rollDice(int max) + { + return static_cast((std::rand() / (static_cast(RAND_MAX)+1.0)) * (max)); + } + +} +} diff --git a/libs/openengine/misc/rng.hpp b/libs/openengine/misc/rng.hpp new file mode 100644 index 0000000000..4e1da17e10 --- /dev/null +++ b/libs/openengine/misc/rng.hpp @@ -0,0 +1,36 @@ +#ifndef MISC_RNG_H +#define MISC_RNG_H + +#include + +namespace OEngine { +namespace Misc +{ + +/* + Provides central implementation of the RNG logic +*/ +class Rng +{ +public: + + /// seed the RNG + static void init(); + + /// return value in range [0.0f, 1.0f) <- note open upper range. + static float rollProbability(); + + /// return value in range [0.0f, 1.0f] <- note closed upper range. + static float rollClosedProbability(); + + /// return value in range [0, max) <- note open upper range. + static int rollDice(int max); + + /// return value in range [0, 99] + static int roll0to99() { return rollDice(100); } +}; + +} +} + +#endif diff --git a/libs/openengine/ogre/lights.cpp b/libs/openengine/ogre/lights.cpp index 348057b846..97fa938da6 100644 --- a/libs/openengine/ogre/lights.cpp +++ b/libs/openengine/ogre/lights.cpp @@ -74,16 +74,16 @@ Ogre::Real LightFunction::calculate(Ogre::Real value) if(mType == LT_Normal) { // Less than 1/255 light modifier for a constant light: - brightness = 1.0 + flickerAmplitude(mDeltaCount*slow)/255.0f; + brightness = 1.0f + flickerAmplitude(mDeltaCount*slow)/255.0f; } else if(mType == LT_Flicker) - brightness = 0.75 + flickerAmplitude(mDeltaCount*fast)*0.25; + brightness = 0.75f + flickerAmplitude(mDeltaCount*fast)*0.25f; else if(mType == LT_FlickerSlow) - brightness = 0.75 + flickerAmplitude(mDeltaCount*slow)*0.25; + brightness = 0.75f + flickerAmplitude(mDeltaCount*slow)*0.25f; else if(mType == LT_Pulse) - brightness = 1.0 + pulseAmplitude(mDeltaCount*fast)*0.25; + brightness = 1.0f + pulseAmplitude(mDeltaCount*fast)*0.25f; else if(mType == LT_PulseSlow) - brightness = 1.0 + pulseAmplitude(mDeltaCount*slow)*0.25; + brightness = 1.0f + pulseAmplitude(mDeltaCount*slow)*0.25f; return brightness; } diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 0e37d28025..bdeeeb8c4b 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -184,7 +184,7 @@ void OgreRenderer::setWindowGammaContrast(float gamma, float contrast) if (value > 65535) value = 65535; else if (value < 0) value = 0; - red[i] = green[i] = blue[i] = value; + red[i] = green[i] = blue[i] = static_cast(value); } if (SDL_SetWindowGammaRamp(mSDLWindow, red, green, blue) < 0) std::cout << "Couldn't set gamma: " << SDL_GetError() << std::endl; diff --git a/libs/openengine/ogre/selectionbuffer.cpp b/libs/openengine/ogre/selectionbuffer.cpp index 0ca24676e0..741b672ff1 100644 --- a/libs/openengine/ogre/selectionbuffer.cpp +++ b/libs/openengine/ogre/selectionbuffer.cpp @@ -10,6 +10,8 @@ #include +#include + #include namespace OEngine @@ -26,7 +28,7 @@ namespace Render setupRenderTarget(); - mCurrentColour = Ogre::ColourValue(0.3, 0.3, 0.3); + mCurrentColour = Ogre::ColourValue(0.3f, 0.3f, 0.3f); } void SelectionBuffer::setupRenderTarget() @@ -145,7 +147,7 @@ namespace Render void SelectionBuffer::getNextColour () { - Ogre::ARGB color = (float(rand()) / float(RAND_MAX)) * std::numeric_limits::max(); + Ogre::ARGB color = static_cast(OEngine::Misc::Rng::rollClosedProbability() * std::numeric_limits::max()); if (mCurrentColour.getAsARGB () == color) { diff --git a/libs/openengine/testall.sh b/libs/openengine/testall.sh deleted file mode 100755 index 097fdabd5b..0000000000 --- a/libs/openengine/testall.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -function run() -{ - echo "TESTING $1" - cd "$1/tests/" - ./test.sh - cd ../../ -} - -run input diff --git a/libs/platform/string.h b/libs/platform/string.h deleted file mode 100644 index 5368d757cc..0000000000 --- a/libs/platform/string.h +++ /dev/null @@ -1,34 +0,0 @@ -// Wrapper for string.h on Mac and MinGW -#ifndef _STRING_WRAPPER_H -#define _STRING_WRAPPER_H - -#ifdef __APPLE__ -#include -#endif - -#include -#if (defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070) || defined(__MINGW32__) -// need our own implementation of strnlen -#ifdef __MINGW32__ -static size_t strnlen(const char *s, size_t n) -{ - const char *p = (const char *)memchr(s, 0, n); - return(p ? p-s : n); -} -#elif (defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070) -static size_t mw_strnlen(const char *s, size_t n) -{ - if (strnlen != NULL) { - return strnlen(s, n); - } - else { - const char *p = (const char *)memchr(s, 0, n); - return(p ? p-s : n); - } -} -#define strnlen mw_strnlen -#endif - -#endif - -#endif