1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-31 00:15:35 +00:00

Merge branch 'master' of https://github.com/OpenMW/openmw into osg

Conflicts:
	apps/opencs/model/doc/document.cpp
	apps/opencs/model/doc/documentmanager.cpp
	components/CMakeLists.txt
	components/bsa/resources.cpp
	components/nif/data.hpp
	components/nif/node.cpp
	components/nifogre/mesh.hpp
	components/nifogre/ogrenifloader.cpp
	components/nifogre/particles.cpp
This commit is contained in:
scrawl 2015-03-27 17:30:48 +01:00
commit 236d628884
480 changed files with 5184 additions and 3591 deletions

View file

@ -21,6 +21,14 @@ addons:
build_command_prepend: "cmake ." build_command_prepend: "cmake ."
build_command: "make -j3" build_command: "make -j3"
branch_pattern: coverity_scan 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: before_install:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi - 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 - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script: script:
- cd ./build - 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 - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
after_script: after_script:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi

View file

@ -39,6 +39,8 @@ Programmers
Eli2 Eli2
Emanuel Guével (potatoesmaster) Emanuel Guével (potatoesmaster)
eroen eroen
escondida
Evgeniy Mineev (sandstranger)
Fil Krynicki (filkry) Fil Krynicki (filkry)
Gašper Sedej Gašper Sedej
gugus/gus gugus/gus
@ -91,7 +93,6 @@ Programmers
Rohit Nirmal Rohit Nirmal
Roman Melnik (Kromgart) Roman Melnik (Kromgart)
Roman Proskuryakov (humbug) Roman Proskuryakov (humbug)
sandstranger
Sandy Carter (bwrsandman) Sandy Carter (bwrsandman)
Scott Howard Scott Howard
Sebastian Wick (swick) Sebastian Wick (swick)

View file

@ -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 0.35.0
------ ------

View file

@ -1,7 +1,12 @@
#!/bin/sh #!/bin/sh
export CXX=g++ if [ "${ANALYZE}" ]; then
export CC=gcc 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 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 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 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 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 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 sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1 sudo cmake .. -DBUILD_SHARED_LIBS=1

View file

@ -2,4 +2,6 @@
mkdir build mkdir build
cd 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

View file

@ -20,7 +20,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 35) set(OPENMW_VERSION_MINOR 35)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 1)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "") set(OPENMW_VERSION_TAGHASH "")
@ -98,43 +98,6 @@ endif()
# We probably support older versions than this. # We probably support older versions than this.
cmake_minimum_required(VERSION 2.6) 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 # Sound setup
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
unset(FFMPEG_LIBRARIES CACHE) unset(FFMPEG_LIBRARIES CACHE)
@ -270,7 +233,8 @@ endif ()
endif(WIN32) endif(WIN32)
endif(OGRE_STATIC) 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} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR}
${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}
@ -279,7 +243,7 @@ include_directories("."
${MYGUI_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS} ${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LIBS_DIR} ${BULLET_INCLUDE_DIRS}
) )
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
@ -379,6 +343,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) "${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) if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop") "${OpenMW_BINARY_DIR}/openmw.desktop")
@ -386,22 +353,22 @@ if (NOT WIN32 AND NOT APPLE)
"${OpenMW_BINARY_DIR}/openmw-cs.desktop") "${OpenMW_BINARY_DIR}/openmw-cs.desktop")
endif() endif()
# Compiler settings # CXX Compiler settings
if (CMAKE_COMPILER_IS_GNUCC) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
if ("${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 "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter")
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) endif(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
elseif (MSVC) elseif (MSVC)
# Enable link-time code generation globally for all linking # Enable link-time code generation globally for all linking
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") 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_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_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) IF(NOT WIN32 AND NOT APPLE)
# Linux building # Linux building
@ -468,6 +435,8 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") 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}/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}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
@ -488,6 +457,7 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt"
"${OpenMW_BINARY_DIR}/Release/openmw.exe" "${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".") DESTINATION ".")
@ -572,6 +542,10 @@ if(WIN32)
include(CPack) include(CPack)
endif(WIN32) endif(WIN32)
# Libs
include_directories(libs)
add_subdirectory(libs/openengine)
# Extern # Extern
#add_subdirectory (extern/shiny) #add_subdirectory (extern/shiny)
#add_subdirectory (extern/ogre-ffmpeg-videoplayer) #add_subdirectory (extern/ogre-ffmpeg-videoplayer)
@ -682,6 +656,7 @@ if (WIN32)
4193 # #pragma warning(pop) : no matching '#pragma warning(push)' 4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY' 4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY' 4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
4315 # undocumented, 'this' pointer for member might not be aligned (OgreMemoryStlAllocator.h)
# caused by boost # caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
@ -689,6 +664,7 @@ if (WIN32)
# OpenMW specific warnings # OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type 4099 # Type mismatch, declared class or struct is defined with other type
4100 # Unreferenced formal parameter (-Wunused-parameter) 4100 # Unreferenced formal parameter (-Wunused-parameter)
4101 # Unreferenced local variable (-Wunused-variable)
4127 # Conditional expression is constant 4127 # Conditional expression is constant
4242 # Storing value in a variable of a smaller type, possible loss of data 4242 # Storing value in a variable of a smaller type, possible loss of data
4244 # Storing value of one type in variable of another (size_t in int, for example) 4244 # Storing value of one type in variable of another (size_t in int, for example)
@ -707,56 +683,23 @@ if (WIN32)
set(WARNINGS "${WARNINGS} /wd${d}") set(WARNINGS "${WARNINGS} /wd${d}")
endforeach(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 # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245") set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}") set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
# there's an unreferenced local variable in the ogre platform, suppress it
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${SHINY_OGRE_WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable # oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189") set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}") set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
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) if (BUILD_OPENCS)
# QT triggers an informational warning that the object layout may differ when compiled with /vd2 # QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435") set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS}) set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS) endif (BUILD_OPENCS)
if (BUILD_MWINIIMPORTER)
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC) 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 # 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_RELEASE "/SUBSYSTEM:WINDOWS")
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
@ -770,6 +713,7 @@ if (APPLE)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/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}/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}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)

View file

@ -6,7 +6,7 @@ OpenMW
OpenMW is an attempt at recreating the engine for the popular role-playing game 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. 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) * License: GPL (see docs/license/GPL3.txt for more information)
* Website: http://www.openmw.org * Website: http://www.openmw.org
* IRC: #openmw on irc.freenode.net * IRC: #openmw on irc.freenode.net

View file

@ -461,7 +461,7 @@ int clone(Arguments& info)
for (Stats::iterator it = stats.begin(); it != stats.end(); ++it) for (Stats::iterator it = stats.begin(); it != stats.end(); ++it)
{ {
name.val = it->first; name.val = it->first;
float amount = it->second; int amount = it->second;
std::cout << std::setw(digitCount) << amount << " " << name.toString() << " "; std::cout << std::setw(digitCount) << amount << " " << name.toString() << " ";
if (++i % 3 == 0) if (++i % 3 == 0)

View file

@ -6,6 +6,9 @@
#include <boost/format.hpp> #include <boost/format.hpp>
namespace
{
void printAIPackage(ESM::AIPackage p) void printAIPackage(ESM::AIPackage p)
{ {
std::cout << " AI Type: " << aiTypeLabel(p.mType) 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 << " Duration: " << p.mWander.mDuration << std::endl;
std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl; std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl;
if (p.mWander.mShouldRepeat != 1) 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: "; std::cout << " Idle: ";
for (int i = 0; i != 8; i++) for (int i = 0; i != 8; i++)
@ -149,6 +152,26 @@ void printEffectList(ESM::EffectList effects)
} }
} }
void printTransport(const std::vector<ESM::Transport::Dest>& transport)
{
std::vector<ESM::Transport::Dest>::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 { namespace EsmTool {
RecordBase * RecordBase *
@ -631,6 +654,8 @@ void Record<ESM::Creature>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
printTransport(mData.getTransport());
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl; std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
@ -1042,20 +1067,7 @@ void Record<ESM::NPC>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit; printTransport(mData.getTransport());
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;
}
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
@ -1253,7 +1265,7 @@ void Record<ESM::Spell>::print()
template<> template<>
void Record<ESM::StartScript>::print() void Record<ESM::StartScript>::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; std::cout << "Start Data: " << mData.mData << std::endl;
} }

View file

@ -23,18 +23,18 @@ namespace ESSImport
} }
for (int i=0; i<8; ++i) for (int i=0; i<8; ++i)
{ {
cStats.mAttributes[i].mBase = acdt.mAttributes[i][1]; cStats.mAttributes[i].mBase = static_cast<int>(acdt.mAttributes[i][1]);
cStats.mAttributes[i].mMod = acdt.mAttributes[i][0]; cStats.mAttributes[i].mMod = static_cast<int>(acdt.mAttributes[i][0]);
cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0]; cStats.mAttributes[i].mCurrent = static_cast<int>(acdt.mAttributes[i][0]);
} }
cStats.mGoldPool = acdt.mGoldPool; cStats.mGoldPool = acdt.mGoldPool;
cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer; cStats.mTalkedTo = (acdt.mFlags & TalkedToPlayer) != 0;
cStats.mAttacked = acdt.mFlags & Attacked; cStats.mAttacked = (acdt.mFlags & Attacked) != 0;
} }
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats) 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) void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)

View file

@ -553,7 +553,7 @@ public:
ESM::WeatherState weather; ESM::WeatherState weather;
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather); weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather); 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.mHour = mContext->mHour;
weather.mWindSpeed = 0.f; weather.mWindSpeed = 0.f;
weather.mTimePassed = 0.0; weather.mTimePassed = 0.0;

View file

@ -43,13 +43,17 @@ namespace ESSImport
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
unsigned char mUnknown4[4]; unsigned char mUnknown4[4];
unsigned int mGoldPool; unsigned int mGoldPool;
unsigned char mUnknown5[4]; unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
// this one is for respawning?
unsigned char mUnknown5[3];
}; };
struct ACSC struct ACSC
{ {
unsigned char mUnknown1[17]; unsigned char mUnknown1[17];
unsigned char mFlags; // ACSCFlags unsigned char mFlags; // ACSCFlags
unsigned char mUnknown2[94]; unsigned char mUnknown2[22];
unsigned char mCorpseClearCountdown; // hours?
unsigned char mUnknown3[71];
}; };
#pragma pack(pop) #pragma pack(pop)

View file

@ -43,7 +43,7 @@ namespace ESSImport
{ {
unsigned int deleted; unsigned int deleted;
esm.getHT(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")) if (esm.isNextSub("MVRF"))

View file

@ -14,10 +14,10 @@ namespace ESSImport
float scale; float scale;
esm.getHNOT(scale, "XSCL"); esm.getHNOT(scale, "XSCL");
// FIXME: use AiPackageList, need to fix getSubName()
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|| esm.isNextSub("AI_A")) || esm.isNextSub("AI_A"))
esm.skipHSub(); mAiPackages.add(esm);
mInventory.load(esm); mInventory.load(esm);
} }

View file

@ -2,6 +2,7 @@
#define OPENMW_ESSIMPORT_CREC_H #define OPENMW_ESSIMPORT_CREC_H
#include "importinventory.hpp" #include "importinventory.hpp"
#include <components/esm/aipackage.hpp>
namespace ESM namespace ESM
{ {
@ -17,6 +18,7 @@ namespace ESSImport
int mIndex; int mIndex;
Inventory mInventory; Inventory mInventory;
ESM::AIPackageList mAiPackages;
void load(ESM::ESMReader& esm); void load(ESM::ESMReader& esm);
}; };

View file

@ -9,10 +9,9 @@ namespace ESSImport
{ {
esm.getHNT(mNPDT, "NPDT"); esm.getHNT(mNPDT, "NPDT");
// FIXME: use AiPackageList, need to fix getSubName()
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|| esm.isNextSub("AI_A")) || esm.isNextSub("AI_A"))
esm.skipHSub(); mAiPackages.add(esm);
mInventory.load(esm); mInventory.load(esm);
} }

View file

@ -27,6 +27,7 @@ namespace ESSImport
} mNPDT; } mNPDT;
Inventory mInventory; Inventory mInventory;
ESM::AIPackageList mAiPackages;
void load(ESM::ESMReader &esm); void load(ESM::ESMReader &esm);
}; };

View file

@ -61,6 +61,7 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
QString revision(OPENMW_VERSION_COMMITHASH); QString revision(OPENMW_VERSION_COMMITHASH);
QString tag(OPENMW_VERSION_TAGHASH); QString tag(OPENMW_VERSION_TAGHASH);
versionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
if (!revision.isEmpty() && !tag.isEmpty()) if (!revision.isEmpty() && !tag.isEmpty())
{ {
if (revision == tag) { if (revision == tag) {
@ -238,24 +239,8 @@ void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem
current = previous; current = previous;
int currentIndex = iconWidget->row(current); int currentIndex = iconWidget->row(current);
// int previousIndex = iconWidget->row(previous);
pagesWidget->setCurrentIndex(currentIndex); pagesWidget->setCurrentIndex(currentIndex);
mSettingsPage->resetProgressBar();
// DataFilesPage *previousPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(previousIndex));
// DataFilesPage *currentPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(currentIndex));
// //special call to update/save data files page list view when it's displayed/hidden.
// if (previousPage)
// {
// if (previousPage->objectName() == "DataFilesPage")
// previousPage->saveSettings();
// }
// else if (currentPage)
// {
// if (currentPage->objectName() == "DataFilesPage")
// currentPage->loadSettings();
// }
} }
bool Launcher::MainDialog::setupLauncherSettings() bool Launcher::MainDialog::setupLauncherSettings()

View file

@ -39,6 +39,7 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
mWizardInvoker = new ProcessInvoker(); mWizardInvoker = new ProcessInvoker();
mImporterInvoker = new ProcessInvoker(); mImporterInvoker = new ProcessInvoker();
resetProgressBar();
connect(mWizardInvoker->getProcess(), SIGNAL(started()), connect(mWizardInvoker->getProcess(), SIGNAL(started()),
this, SLOT(wizardStarted())); this, SLOT(wizardStarted()));
@ -94,7 +95,7 @@ Launcher::SettingsPage::~SettingsPage()
void Launcher::SettingsPage::on_wizardButton_clicked() void Launcher::SettingsPage::on_wizardButton_clicked()
{ {
saveSettings(); mMain->writeSettings();
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false)) if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
return; return;
@ -102,7 +103,7 @@ void Launcher::SettingsPage::on_wizardButton_clicked()
void Launcher::SettingsPage::on_importerButton_clicked() void Launcher::SettingsPage::on_importerButton_clicked()
{ {
saveSettings(); mMain->writeSettings();
// Create the file if it doesn't already exist, else the importer will fail // Create the file if it doesn't already exist, else the importer will fail
QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()));
@ -141,8 +142,13 @@ void Launcher::SettingsPage::on_importerButton_clicked()
qDebug() << "arguments " << arguments; qDebug() << "arguments " << arguments;
// start the progress bar as a "bouncing ball"
progressBar->setMaximum(0);
progressBar->setValue(0);
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false)) if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
return; {
resetProgressBar();
}
} }
void Launcher::SettingsPage::on_browseButton_clicked() void Launcher::SettingsPage::on_browseButton_clicked()
@ -197,38 +203,35 @@ void Launcher::SettingsPage::importerStarted()
void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus) void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus)
{ {
if (exitCode != 0 || exitStatus == QProcess::CrashExit) if (exitCode != 0 || exitStatus == QProcess::CrashExit)
return; {
resetProgressBar();
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Importer finished"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(tr("Failed to import settings from INI file."));
msgBox.exec();
}
else
{
// indicate progress finished
progressBar->setMaximum(1);
progressBar->setValue(1);
// Importer may have changed settings, so refresh // Importer may have changed settings, so refresh
mMain->reloadSettings(); mMain->reloadSettings();
// Import selected data files from openmw.cfg
if (addonsCheckBox->isChecked())
{
// Because we've reloaded settings, the current content list matches content in OpenMW.cfg
QString oldContentListName = mLauncherSettings.getCurrentContentListName();
if (mProfileDialog->exec() == QDialog::Accepted)
{
// remove the current content list to prevent duplication
//... except, not allowed to delete the Default content list
if (oldContentListName.compare(DataFilesPage::mDefaultContentListName) != 0)
{
mLauncherSettings.removeContentList(oldContentListName);
}
const QString newContentListName(mProfileDialog->lineEdit()->text());
const QStringList files(mGameSettings.getContentList());
mLauncherSettings.setCurrentContentListName(newContentListName);
mLauncherSettings.setContentList(newContentListName, files);
// Make DataFiles Page load the new content list.
mMain->reloadSettings();
}
} }
importerButton->setEnabled(true); importerButton->setEnabled(true);
} }
void Launcher::SettingsPage::resetProgressBar()
{
// set progress bar to 0 %
progressBar->reset();
}
void Launcher::SettingsPage::updateOkButton(const QString &text) void Launcher::SettingsPage::updateOkButton(const QString &text)
{ {
// We do this here because we need to access the profiles // We do this here because we need to access the profiles

View file

@ -30,6 +30,9 @@ namespace Launcher
void saveSettings(); void saveSettings();
bool loadSettings(); bool loadSettings();
/// set progress bar on page to 0%
void resetProgressBar();
private slots: private slots:
void on_wizardButton_clicked(); void on_wizardButton_clicked();
@ -57,7 +60,6 @@ namespace Launcher
MainDialog *mMain; MainDialog *mMain;
TextInputDialog *mProfileDialog; TextInputDialog *mProfileDialog;
}; };
} }

View file

@ -8,7 +8,8 @@
#include <sstream> #include <sstream>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <boost/filesystem/path.hpp> #include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
namespace bfs = boost::filesystem; namespace bfs = boost::filesystem;
@ -660,7 +661,7 @@ std::string MwIniImporter::numberToString(int n) {
return str.str(); return str.str();
} }
MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filename) const { MwIniImporter::multistrmap MwIniImporter::loadIniFile(const boost::filesystem::path& filename) const {
std::cout << "load ini file: " << filename << std::endl; std::cout << "load ini file: " << filename << std::endl;
std::string section(""); std::string section("");
@ -719,7 +720,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
return map; return map;
} }
MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filename) { MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const boost::filesystem::path& filename) {
std::cout << "load cfg file: " << filename << std::endl; std::cout << "load cfg file: " << filename << std::endl;
MwIniImporter::multistrmap map; MwIniImporter::multistrmap map;
@ -825,10 +826,14 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
} }
} }
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const { void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, const boost::filesystem::path& iniFilename) const {
std::vector<std::string> contentFiles; std::vector<std::pair<std::time_t, std::string> > contentFiles;
std::string baseGameFile("Game Files:GameFile"); std::string baseGameFile("Game Files:GameFile");
std::string gameFile(""); std::string gameFile("");
std::time_t defaultTime = 0;
// assume the Game Files are all in a "Data Files" directory under the directory holding Morrowind.ini
const boost::filesystem::path gameFilesDir(iniFilename.parent_path() /= "Data Files");
multistrmap::const_iterator it = ini.begin(); multistrmap::const_iterator it = ini.begin();
for(int i=0; it != ini.end(); i++) { for(int i=0; it != ini.end(); i++) {
@ -845,18 +850,20 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
Misc::StringUtils::toLower(filetype); Misc::StringUtils::toLower(filetype);
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) { if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
contentFiles.push_back(*entry); boost::filesystem::path filepath(gameFilesDir);
filepath /= *entry;
contentFiles.push_back(std::make_pair(lastWriteTime(filepath, defaultTime), *entry));
} }
} }
gameFile = "";
} }
cfg.erase("content"); cfg.erase("content");
cfg.insert( std::make_pair("content", std::vector<std::string>() ) ); cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
for(std::vector<std::string>::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) { // this will sort files by time order first, then alphabetical (maybe), I suspect non ASCII filenames will be stuffed.
cfg["content"].push_back(*it); sort(contentFiles.begin(), contentFiles.end());
for(std::vector<std::pair<std::time_t, std::string> >::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
cfg["content"].push_back(it->second);
} }
} }
@ -873,3 +880,27 @@ void MwIniImporter::setInputEncoding(const ToUTF8::FromType &encoding)
{ {
mEncoding = encoding; mEncoding = encoding;
} }
std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime)
{
std::time_t writeTime(defaultTime);
if (boost::filesystem::exists(filename))
{
// FixMe: remove #if when Boost dependency for Linux builds updated
// This allows Linux to build until then
#if (BOOST_VERSION >= 104800)
// need to resolve any symlinks so that we get time of file, not symlink
boost::filesystem::path resolved = boost::filesystem::canonical(filename);
#else
boost::filesystem::path resolved = filename;
#endif
writeTime = boost::filesystem::last_write_time(resolved);
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
") " << asctime(localtime(&writeTime)) << std::endl;
}
else
{
std::cout << "content file: " << filename << " not found" << std::endl;
}
return writeTime;
}

View file

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include <exception> #include <exception>
#include <iosfwd> #include <iosfwd>
#include <boost/filesystem/path.hpp>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
@ -17,17 +18,22 @@ class MwIniImporter {
MwIniImporter(); MwIniImporter();
void setInputEncoding(const ToUTF8::FromType& encoding); void setInputEncoding(const ToUTF8::FromType& encoding);
void setVerbose(bool verbose); void setVerbose(bool verbose);
multistrmap loadIniFile(const std::string& filename) const; multistrmap loadIniFile(const boost::filesystem::path& filename) const;
static multistrmap loadCfgFile(const std::string& filename); static multistrmap loadCfgFile(const boost::filesystem::path& filename);
void merge(multistrmap &cfg, const multistrmap &ini) const; void merge(multistrmap &cfg, const multistrmap &ini) const;
void mergeFallback(multistrmap &cfg, const multistrmap &ini) const; void mergeFallback(multistrmap &cfg, const multistrmap &ini) const;
void importGameFiles(multistrmap &cfg, const multistrmap &ini) const; void importGameFiles(multistrmap &cfg, const multistrmap &ini,
const boost::filesystem::path& iniFilename) const;
void importArchives(multistrmap &cfg, const multistrmap &ini) const; void importArchives(multistrmap &cfg, const multistrmap &ini) const;
static void writeToFile(std::ostream &out, const multistrmap &cfg); static void writeToFile(std::ostream &out, const multistrmap &cfg);
private: private:
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value); static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
static std::string numberToString(int n); static std::string numberToString(int n);
/// \return file's "last modified time", used in original MW to determine plug-in load order
static std::time_t lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime);
bool mVerbose; bool mVerbose;
strmap mMergeMap; strmap mMergeMap;
std::vector<std::string> mMergeFallback; std::vector<std::string> mMergeFallback;

View file

@ -93,8 +93,8 @@ int wmain(int argc, wchar_t *wargv[]) {
bpo::notify(vm); bpo::notify(vm);
std::string iniFile = vm["ini"].as<std::string>(); boost::filesystem::path iniFile(vm["ini"].as<std::string>());
std::string cfgFile = vm["cfg"].as<std::string>(); boost::filesystem::path cfgFile(vm["cfg"].as<std::string>());
// if no output is given, write back to cfg file // if no output is given, write back to cfg file
std::string outputFile(vm["output"].as<std::string>()); std::string outputFile(vm["output"].as<std::string>());
@ -110,7 +110,7 @@ int wmain(int argc, wchar_t *wargv[]) {
std::cerr << "cfg file does not exist" << std::endl; std::cerr << "cfg file does not exist" << std::endl;
MwIniImporter importer; MwIniImporter importer;
importer.setVerbose(vm.count("verbose")); importer.setVerbose(vm.count("verbose") != 0);
// Font encoding settings // Font encoding settings
std::string encoding(vm["encoding"].as<std::string>()); std::string encoding(vm["encoding"].as<std::string>());
@ -123,7 +123,7 @@ int wmain(int argc, wchar_t *wargv[]) {
importer.mergeFallback(cfg, ini); importer.mergeFallback(cfg, ini);
if(vm.count("game-files")) { if(vm.count("game-files")) {
importer.importGameFiles(cfg, ini); importer.importGameFiles(cfg, ini, iniFile);
} }
if(!vm.count("no-archives")) { if(!vm.count("no-archives")) {

View file

@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp
opencs_units (. editor) opencs_units (. editor)
opencs_units (model/doc opencs_units (model/doc
document operation saving documentmanager loader runner document operation saving documentmanager loader runner operationholder
) )
opencs_units_noqt (model/doc opencs_units_noqt (model/doc
@ -40,6 +40,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
startscriptcheck
) )
@ -164,7 +165,8 @@ qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) 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) if(APPLE)
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns) set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
@ -174,7 +176,6 @@ endif(APPLE)
add_executable(openmw-cs add_executable(openmw-cs
MACOSX_BUNDLE MACOSX_BUNDLE
${OENGINE_BULLET}
${OPENCS_SRC} ${OPENCS_SRC}
${OPENCS_UI_HDR} ${OPENCS_UI_HDR}
${OPENCS_MOC_SRC} ${OPENCS_MOC_SRC}
@ -198,6 +199,7 @@ if(APPLE)
endif(APPLE) endif(APPLE)
target_link_libraries(openmw-cs target_link_libraries(openmw-cs
${OENGINE_LIBRARY}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES} ${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS} ${OGRE_STATIC_PLUGINS}

View file

@ -2252,7 +2252,8 @@ CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationM
mTools (*this), mResDir(resDir), mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation),
mRunner (mProjectPath) mRunner (mProjectPath)
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())

View file

@ -20,6 +20,7 @@
#include "saving.hpp" #include "saving.hpp"
#include "blacklist.hpp" #include "blacklist.hpp"
#include "runner.hpp" #include "runner.hpp"
#include "operationholder.hpp"
class QAbstractItemModel; class QAbstractItemModel;
@ -38,7 +39,7 @@ namespace ESM
namespace Files namespace Files
{ {
class ConfigurationManager; struct ConfigurationManager;
} }
namespace CSMWorld namespace CSMWorld
@ -61,7 +62,8 @@ namespace CSMDoc
CSMWorld::Data mData; CSMWorld::Data mData;
CSMTools::Tools mTools; CSMTools::Tools mTools;
boost::filesystem::path mProjectPath; boost::filesystem::path mProjectPath;
Saving mSaving; Saving mSavingOperation;
OperationHolder mSaving;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;

View file

@ -22,7 +22,7 @@ namespace VFS
namespace Files namespace Files
{ {
class ConfigurationManager; struct ConfigurationManager;
} }
namespace CSMDoc namespace CSMDoc

View file

@ -29,9 +29,9 @@ void CSMDoc::Operation::prepareStages()
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()), : mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), 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() CSMDoc::Operation::~Operation()
@ -42,15 +42,17 @@ CSMDoc::Operation::~Operation()
void CSMDoc::Operation::run() void CSMDoc::Operation::run()
{ {
mTimer->stop();
if (!mConnected)
{
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
mConnected = true;
}
prepareStages(); prepareStages();
QTimer timer; mTimer->start (0);
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
timer.start (0);
exec();
} }
void CSMDoc::Operation::appendStage (Stage *stage) void CSMDoc::Operation::appendStage (Stage *stage)
@ -65,7 +67,7 @@ bool CSMDoc::Operation::hasError() const
void CSMDoc::Operation::abort() void CSMDoc::Operation::abort()
{ {
if (!isRunning()) if (!mTimer->isActive())
return; return;
mError = true; mError = true;
@ -116,10 +118,11 @@ void CSMDoc::Operation::executeStage()
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
if (mCurrentStage==mStages.end()) if (mCurrentStage==mStages.end())
exit(); operationDone();
} }
void CSMDoc::Operation::operationDone() void CSMDoc::Operation::operationDone()
{ {
mTimer->stop();
emit done (mType, mError); emit done (mType, mError);
} }

View file

@ -3,7 +3,8 @@
#include <vector> #include <vector>
#include <QThread> #include <QObject>
#include <QTimer>
namespace CSMWorld namespace CSMWorld
{ {
@ -14,7 +15,7 @@ namespace CSMDoc
{ {
class Stage; class Stage;
class Operation : public QThread class Operation : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +28,8 @@ namespace CSMDoc
int mOrdered; int mOrdered;
bool mFinalAlways; bool mFinalAlways;
bool mError; bool mError;
bool mConnected;
QTimer *mTimer;
void prepareStages(); void prepareStages();
@ -38,8 +41,6 @@ namespace CSMDoc
virtual ~Operation(); virtual ~Operation();
virtual void run();
void appendStage (Stage *stage); void appendStage (Stage *stage);
///< The ownership of \a stage is transferred to *this. ///< The ownership of \a stage is transferred to *this.
/// ///
@ -60,6 +61,8 @@ namespace CSMDoc
void abort(); void abort();
void run();
private slots: private slots:
void executeStage(); void executeStage();

View file

@ -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);
}

View file

@ -0,0 +1,56 @@
#ifndef CSM_DOC_OPERATIONHOLDER_H
#define CSM_DOC_OPERATIONHOLDER_H
#include <QObject>
#include <QThread>
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

View file

@ -6,7 +6,7 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
#include "operation.hpp" #include "operationholder.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath) CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (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) : QObject (runner), mRunner (runner)
{ {
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool))); connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));

View file

@ -16,6 +16,8 @@ class QTemporaryFile;
namespace CSMDoc namespace CSMDoc
{ {
class OperationHolder;
class Runner : public QObject class Runner : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -74,7 +76,7 @@ namespace CSMDoc
public: public:
/// *this attaches itself to runner /// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation); SaveWatcher (Runner *runner, OperationHolder *operation);
private slots: private slots:

View file

@ -78,6 +78,9 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> > appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
(mDocument.getData().getMagicEffects(), mState)); (mDocument.getData().getMagicEffects(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
(mDocument.getData().getStartScripts(), mState));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
@ -90,6 +93,10 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WritePathgridCollectionStage (mDocument, mState)); appendStage (new WritePathgridCollectionStage (mDocument, mState));
appendStage (new WriteLandCollectionStage (mDocument, mState));
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
// close file and clean up // close file and clean up
appendStage (new CloseSaveStage (mState)); appendStage (new CloseSaveStage (mState));

View file

@ -90,7 +90,7 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document, CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document,
SavingState& state, bool journal) SavingState& state, bool journal)
: mDocument (document), mState (state), : mState (state),
mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()), mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()),
mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos()) 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<CSMWorld::Land>& 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<CSMWorld::LandTexture>& 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) CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
: mState (state) : mState (state)
{} {}

View file

@ -7,6 +7,8 @@
#include "../world/idcollection.hpp" #include "../world/idcollection.hpp"
#include "../world/scope.hpp" #include "../world/scope.hpp"
#include <components/esm/defs.hpp>
#include "savingstate.hpp" #include "savingstate.hpp"
namespace ESM namespace ESM
@ -103,7 +105,14 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified || if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly) state==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); // 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)); mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter()); mCollection.getRecord (stage).mModified.save (mState.getWriter());
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId); mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
@ -117,7 +126,6 @@ namespace CSMDoc
class WriteDialogueCollectionStage : public Stage class WriteDialogueCollectionStage : public Stage
{ {
Document& mDocument;
SavingState& mState; SavingState& mState;
const CSMWorld::IdCollection<ESM::Dialogue>& mTopics; const CSMWorld::IdCollection<ESM::Dialogue>& mTopics;
CSMWorld::InfoCollection& mInfos; CSMWorld::InfoCollection& mInfos;
@ -200,6 +208,40 @@ namespace CSMDoc
///< Messages resulting from this stage will be appended to \a messages. ///< 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 class CloseSaveStage : public Stage
{ {
SavingState& mState; SavingState& mState;

View file

@ -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 object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1) if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner)); 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 // Check item's faction rank
if (hasFaction && cellRef.mFactionRank < -1) 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<std::string>(cellRef.mFactionRank)));
else if (!hasFaction && cellRef.mFactionRank != -2) 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<std::string>(cellRef.mFactionRank)));
// If door have destination cell, check if that reference is valid // If door have destination cell, check if that reference is valid
if (!cellRef.mDestCell.empty()) if (!cellRef.mDestCell.empty())

View file

@ -0,0 +1,31 @@
#include "startscriptcheck.hpp"
#include <components/misc/stringops.hpp>
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts)
: mStartScripts (startScripts), mScripts (scripts)
{}
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
{
const CSMWorld::Record<ESM::StartScript>& 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();
}

View file

@ -0,0 +1,28 @@
#ifndef CSM_TOOLS_STARTSCRIPTCHECK_H
#define CSM_TOOLS_STARTSCRIPTCHECK_H
#include <components/esm/loadsscr.hpp>
#include <components/esm/loadscpt.hpp>
#include "../doc/stage.hpp"
#include "../world/idcollection.hpp"
namespace CSMTools
{
class StartScriptCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
const CSMWorld::IdCollection<ESM::Script>& mScripts;
public:
StartScriptCheckStage (const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts);
virtual void perform(int stage, CSMDoc::Messages& messages);
virtual int setup();
};
}
#endif

View file

@ -24,31 +24,32 @@
#include "scriptcheck.hpp" #include "scriptcheck.hpp"
#include "bodypartcheck.hpp" #include "bodypartcheck.hpp"
#include "referencecheck.hpp" #include "referencecheck.hpp"
#include "startscriptcheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type) CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{ {
switch (type) switch (type)
{ {
case CSMDoc::State_Verifying: return mVerifier; case CSMDoc::State_Verifying: return &mVerifier;
} }
return 0; return 0;
} }
const CSMDoc::Operation *CSMTools::Tools::get (int type) const const CSMDoc::OperationHolder *CSMTools::Tools::get (int type) const
{ {
return const_cast<Tools *> (this)->get (type); return const_cast<Tools *> (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 (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier, connect (&mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), 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))); this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
@ -58,48 +59,49 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mandatoryIds.push_back ("GameHour"); mandatoryIds.push_back ("GameHour");
mandatoryIds.push_back ("Month"); mandatoryIds.push_back ("Month");
mandatoryIds.push_back ("PCRace"); mandatoryIds.push_back ("PCRace");
mandatoryIds.push_back ("PCVampire");
mandatoryIds.push_back ("PCWerewolf");
mandatoryIds.push_back ("PCYear");
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); 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( new BodyPartCheckStage(
mData.getBodyParts(), mData.getBodyParts(),
mData.getResources( mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() )); mData.getRaces() ));
mVerifier.setOperation (mVerifierOperation);
} }
return mVerifier; return &mVerifier;
} }
CSMTools::Tools::Tools (CSMDoc::Document& document) CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) : mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0)
{ {
// index 0: load error log // index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
@ -108,7 +110,11 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
CSMTools::Tools::~Tools() CSMTools::Tools::~Tools()
{ {
delete mVerifier; if (mVerifierOperation)
{
mVerifier.abortAndWait();
delete mVerifierOperation;
}
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
delete iter->second; delete iter->second;
@ -126,7 +132,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::abortOperation (int type)
{ {
if (CSMDoc::Operation *operation = get (type)) if (CSMDoc::OperationHolder *operation = get (type))
operation->abort(); operation->abort();
} }
@ -141,7 +147,7 @@ int CSMTools::Tools::getRunningOperations() const
int result = 0; int result = 0;
for (int i=0; sOperations[i]!=-1; ++i) 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()) if (operation->isRunning())
result |= sOperations[i]; result |= sOperations[i];

View file

@ -5,6 +5,8 @@
#include <map> #include <map>
#include "../doc/operationholder.hpp"
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
@ -27,7 +29,8 @@ namespace CSMTools
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier; CSMDoc::Operation *mVerifierOperation;
CSMDoc::OperationHolder mVerifier;
std::map<int, ReportModel *> mReports; std::map<int, ReportModel *> mReports;
int mNextReportNumber; int mNextReportNumber;
std::map<int, int> mActiveReports; // type, report number std::map<int, int> mActiveReports; // type, report number
@ -36,12 +39,12 @@ namespace CSMTools
Tools (const Tools&); Tools (const Tools&);
Tools& operator= (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. ///< 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. ///< Returns a 0-pointer, if operation hasn't been used yet.
public: public:

View file

@ -20,7 +20,7 @@ namespace CSMWorld
{ {
class IdTable; class IdTable;
class IdTable; class IdTable;
class RecordBase; struct RecordBase;
class ModifyCommand : public QUndoCommand class ModifyCommand : public QUndoCommand
{ {

View file

@ -254,6 +254,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>); mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid)); mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
mStartScripts.addColumn (new StringIdColumn<ESM::StartScript>);
mStartScripts.addColumn (new RecordStateColumn<ESM::StartScript>);
mStartScripts.addColumn (new FixedRecordTypeColumn<ESM::StartScript> (UniversalId::Type_StartScript));
mRefs.addColumn (new StringIdColumn<CellRef> (true)); mRefs.addColumn (new StringIdColumn<CellRef> (true));
mRefs.addColumn (new RecordStateColumn<CellRef>); mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference)); mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (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 (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid); addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
@ -620,6 +625,16 @@ CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
return mPathgrids; return mPathgrids;
} }
const CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts() const
{
return mStartScripts;
}
CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts()
{
return mStartScripts;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{ {
return mResourcesManager.get (id.getType()); return mResourcesManager.get (id.getType());
@ -724,6 +739,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break; case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break;
case ESM::REC_MGEF: mMagicEffects.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_PGRD: mPathgrids.load (*mReader, mBase); break;
case ESM::REC_SSCR: mStartScripts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break; case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
@ -734,7 +750,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
if (index!=-1 && !mBase) if (index!=-1 && !mBase)
mLand.getRecord (index).mModified.mLand->loadData ( mLand.getRecord (index).mModified.mLand->loadData (
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | 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; break;
} }

View file

@ -25,6 +25,7 @@
#include <components/esm/loadbody.hpp> #include <components/esm/loadbody.hpp>
#include <components/esm/loadsndg.hpp> #include <components/esm/loadsndg.hpp>
#include <components/esm/loadmgef.hpp> #include <components/esm/loadmgef.hpp>
#include <components/esm/loadsscr.hpp>
#include <components/esm/debugprofile.hpp> #include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp> #include <components/esm/filter.hpp>
@ -87,6 +88,7 @@ namespace CSMWorld
SubCellCollection<Pathgrid> mPathgrids; SubCellCollection<Pathgrid> mPathgrids;
IdCollection<ESM::DebugProfile> mDebugProfiles; IdCollection<ESM::DebugProfile> mDebugProfiles;
IdCollection<ESM::SoundGenerator> mSoundGens; IdCollection<ESM::SoundGenerator> mSoundGens;
IdCollection<ESM::StartScript> mStartScripts;
InfoCollection mTopicInfos; InfoCollection mTopicInfos;
InfoCollection mJournalInfos; InfoCollection mJournalInfos;
IdCollection<Cell> mCells; IdCollection<Cell> mCells;
@ -238,6 +240,10 @@ namespace CSMWorld
SubCellCollection<Pathgrid>& getPathgrids(); SubCellCollection<Pathgrid>& getPathgrids();
const IdCollection<ESM::StartScript>& getStartScripts() const;
IdCollection<ESM::StartScript>& getStartScripts();
/// Throws an exception, if \a id does not match a resources list. /// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const; const Resources& getResources (const UniversalId& id) const;

View file

@ -10,7 +10,7 @@
namespace CSMWorld namespace CSMWorld
{ {
class CollectionBase; class CollectionBase;
class RecordBase; struct RecordBase;
class IdTable : public IdTableBase class IdTable : public IdTableBase
{ {

View file

@ -26,7 +26,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (!record2.get().mPrev.empty()) if (!record2.get().mPrev.empty())
{ {
index = getIndex (record2.get().mPrev, topic); index = getInfoIndex (record2.get().mPrev, topic);
if (index!=-1) if (index!=-1)
++index; ++index;
@ -34,7 +34,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (index==-1 && !record2.get().mNext.empty()) if (index==-1 && !record2.get().mNext.empty())
{ {
index = getIndex (record2.get().mNext, topic); index = getInfoIndex (record2.get().mNext, topic);
} }
if (index==-1) 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; std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id;

View file

@ -6,7 +6,7 @@
namespace ESM namespace ESM
{ {
class Dialogue; struct Dialogue;
} }
namespace CSMWorld namespace CSMWorld
@ -22,7 +22,7 @@ namespace CSMWorld
void load (const Info& record, bool base); 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) ///< Return index for record \a id or -1 (if not present; deleted records are considered)
/// ///
/// \param id info ID without topic prefix /// \param id info ID without topic prefix

View file

@ -22,6 +22,8 @@ namespace CSMWorld
virtual RecordBase *clone() const = 0; virtual RecordBase *clone() const = 0;
virtual RecordBase *modifiedCopy() const = 0;
virtual void assign (const RecordBase& record) = 0; virtual void assign (const RecordBase& record) = 0;
///< Will throw an exception if the types don't match. ///< Will throw an exception if the types don't match.
@ -38,8 +40,15 @@ namespace CSMWorld
ESXRecordT mBase; ESXRecordT mBase;
ESXRecordT mModified; ESXRecordT mModified;
Record();
Record(State state,
const ESXRecordT *base = 0, const ESXRecordT *modified = 0);
virtual RecordBase *clone() const; virtual RecordBase *clone() const;
virtual RecordBase *modifiedCopy() const;
virtual void assign (const RecordBase& record); virtual void assign (const RecordBase& record);
const ESXRecordT& get() const; const ESXRecordT& get() const;
@ -58,6 +67,29 @@ namespace CSMWorld
///< Merge modified into base. ///< Merge modified into base.
}; };
template <typename ESXRecordT>
Record<ESXRecordT>::Record()
: mBase(), mModified()
{ }
template <typename ESXRecordT>
Record<ESXRecordT>::Record(State state, const ESXRecordT *base, const ESXRecordT *modified)
{
if(base)
mBase = *base;
if(modified)
mModified = *modified;
this->mState = state;
}
template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::modifiedCopy() const
{
return new Record<ESXRecordT> (State_ModifiedOnly, 0, &(this->get()));
}
template <typename ESXRecordT> template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::clone() const RecordBase *Record<ESXRecordT>::clone() const
{ {

View file

@ -5,8 +5,6 @@
namespace CSMWorld namespace CSMWorld
{ {
class Cell;
/// \brief Wrapper for CellRef sub record /// \brief Wrapper for CellRef sub record
struct CellRef : public ESM::CellRef struct CellRef : public ESM::CellRef
{ {

View file

@ -12,7 +12,7 @@
namespace CSMWorld namespace CSMWorld
{ {
struct Cell; struct Cell;
struct UniversalId; class UniversalId;
/// \brief References in cells /// \brief References in cells
class RefCollection : public Collection<CellRef> class RefCollection : public Collection<CellRef>

View file

@ -9,7 +9,7 @@ namespace CSMWorld
{ {
class RefIdColumn; class RefIdColumn;
class RefIdData; class RefIdData;
class RecordBase; struct RecordBase;
class RefIdAdapter class RefIdAdapter
{ {

View file

@ -156,10 +156,16 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mModel.mModel) if (column==mModel.mModel)
record.get().mModel = value.toString().toUtf8().constData(); record2.mModel = value.toString().toUtf8().constData();
else else
{
BaseRefIdAdapter<RecordT>::setData (column, data, index, value); BaseRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct NameColumns : public ModelColumns struct NameColumns : public ModelColumns
@ -216,12 +222,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mName.mName) if (column==mName.mName)
record.get().mName = value.toString().toUtf8().constData(); record2.mName = value.toString().toUtf8().constData();
else if (column==mName.mScript) else if (column==mName.mScript)
record.get().mScript = value.toString().toUtf8().constData(); record2.mScript = value.toString().toUtf8().constData();
else else
{
ModelRefIdAdapter<RecordT>::setData (column, data, index, value); ModelRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct InventoryColumns : public NameColumns struct InventoryColumns : public NameColumns
@ -283,14 +295,20 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mInventory.mIcon) if (column==mInventory.mIcon)
record.get().mIcon = value.toString().toUtf8().constData(); record2.mIcon = value.toString().toUtf8().constData();
else if (column==mInventory.mWeight) else if (column==mInventory.mWeight)
record.get().mData.mWeight = value.toFloat(); record2.mData.mWeight = value.toFloat();
else if (column==mInventory.mValue) else if (column==mInventory.mValue)
record.get().mData.mValue = value.toInt(); record2.mData.mValue = value.toInt();
else else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value); NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion> class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
@ -364,12 +382,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mEnchantable.mEnchantment) if (column==mEnchantable.mEnchantment)
record.get().mEnchant = value.toString().toUtf8().constData(); record2.mEnchant = value.toString().toUtf8().constData();
else if (column==mEnchantable.mEnchantmentPoints) else if (column==mEnchantable.mEnchantmentPoints)
record.get().mData.mEnchant = value.toInt(); record2.mData.mEnchant = value.toInt();
else else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value); InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct ToolColumns : public InventoryColumns struct ToolColumns : public InventoryColumns
@ -426,12 +450,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mTools.mQuality) if (column==mTools.mQuality)
record.get().mData.mQuality = value.toFloat(); record2.mData.mQuality = value.toFloat();
else if (column==mTools.mUses) else if (column==mTools.mUses)
record.get().mData.mUses = value.toInt(); record2.mData.mUses = value.toInt();
else else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value); InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct ActorColumns : public NameColumns struct ActorColumns : public NameColumns
@ -508,16 +538,17 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mActors.mHasAi) if (column==mActors.mHasAi)
record.get().mHasAI = value.toInt(); record2.mHasAI = value.toInt();
else if (column==mActors.mHello) else if (column==mActors.mHello)
record.get().mAiData.mHello = value.toInt(); record2.mAiData.mHello = value.toInt();
else if (column==mActors.mFlee) else if (column==mActors.mFlee)
record.get().mAiData.mFlee = value.toInt(); record2.mAiData.mFlee = value.toInt();
else if (column==mActors.mFight) else if (column==mActors.mFight)
record.get().mAiData.mFight = value.toInt(); record2.mAiData.mFight = value.toInt();
else if (column==mActors.mAlarm) else if (column==mActors.mAlarm)
record.get().mAiData.mAlarm = value.toInt(); record2.mAiData.mAlarm = value.toInt();
else else
{ {
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter = typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -525,15 +556,20 @@ namespace CSMWorld
if (iter!=mActors.mServices.end()) if (iter!=mActors.mServices.end())
{ {
if (value.toInt()!=0) if (value.toInt()!=0)
record.get().mAiData.mServices |= iter->second; record2.mAiData.mServices |= iter->second;
else else
record.get().mAiData.mServices &= ~iter->second; record2.mAiData.mServices &= ~iter->second;
} }
else else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value); NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
} }
} }
record.setModified(record2);
}
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus> class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>
{ {
const RefIdColumn *mType; const RefIdColumn *mType;

View file

@ -470,8 +470,7 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
const std::string& destination, const std::string& destination,
const CSMWorld::UniversalId::Type type) const CSMWorld::UniversalId::Type type)
{ {
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).clone()); std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).modifiedCopy());
newRecord->mState = RecordBase::State_ModifiedOnly;
mAdapters.find(type)->second->setId(*newRecord, destination); mAdapters.find(type)->second->setId(*newRecord, destination);
mData.insertRecord(*newRecord, type, destination); mData.insertRecord(*newRecord, type, destination);
} }

View file

@ -55,6 +55,7 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 }, { 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_MagicEffects, "Magic Effects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 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 { 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_SoundGen, "Sound Generator", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 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_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 { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };

View file

@ -128,6 +128,8 @@ namespace CSMWorld
Type_MagicEffect, Type_MagicEffect,
Type_Pathgrids, Type_Pathgrids,
Type_Pathgrid, Type_Pathgrid,
Type_StartScripts,
Type_StartScript,
Type_RunLog Type_RunLog
}; };

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -72,8 +73,11 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
{ {
boost::filesystem::path path (name.toUtf8().data()); boost::filesystem::path path (name.toUtf8().data());
bool isLegacyPath = (path.extension() == ".esm" || std::string extension = path.extension().string();
path.extension() == ".esp"); boost::algorithm::to_lower(extension);
bool isLegacyPath = (extension == ".esm" ||
extension == ".esp");
bool isFilePathChanged = (path.parent_path().string() != mLocalData.string()); bool isFilePathChanged = (path.parent_path().string() != mLocalData.string());

View file

@ -147,17 +147,19 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int)
void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool) void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool)
{ {
bool success = (mSelector->selectedFiles().size() > 0); bool success = !mSelector->selectedFiles().empty();
bool isNew = (mAction == ContentAction_New); bool isNew = (mAction == ContentAction_New);
if (isNew) if (isNew)
success = success && !(name.isEmpty()); success = success && !(name.isEmpty());
else else if (success)
{ {
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back(); ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
mAdjusterWidget->setName (file->filePath(), !file->isGameFile()); mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
} }
else
mAdjusterWidget->setName ("", true);
ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success); ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success);
} }

View file

@ -20,7 +20,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
: mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0) : 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); setMinimumWidth (400);

View file

@ -96,7 +96,7 @@ QWidget *CSVDoc::StartupDialogue::createTools()
CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2) CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
{ {
setWindowTitle ("Open CS"); setWindowTitle ("OpenMW-CS");
QVBoxLayout *layout = new QVBoxLayout (this); QVBoxLayout *layout = new QVBoxLayout (this);

View file

@ -26,7 +26,7 @@ void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &)
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{ {
mUniversalId = id; mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str()); setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str()));
} }
void CSVDoc::SubView::closeEvent (QCloseEvent *event) void CSVDoc::SubView::closeEvent (QCloseEvent *event)

View file

@ -173,6 +173,10 @@ void CSVDoc::View::setupMechanicsMenu()
QAction *effects = new QAction (tr ("Magic Effects"), this); QAction *effects = new QAction (tr ("Magic Effects"), this);
connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView())); connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView()));
mechanics->addAction (effects); 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() void CSVDoc::View::setupCharacterMenu()
@ -320,7 +324,7 @@ void CSVDoc::View::updateTitle()
if (hideTitle) if (hideTitle)
stream << " - " << mSubViews.at (0)->getTitle(); stream << " - " << mSubViews.at (0)->getTitle();
setWindowTitle (stream.str().c_str()); setWindowTitle (QString::fromUtf8(stream.str().c_str()));
} }
void CSVDoc::View::updateSubViewIndicies(SubView *view) void CSVDoc::View::updateSubViewIndicies(SubView *view)
@ -481,6 +485,8 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
(!isReferenceable && id == sb->getUniversalId())) (!isReferenceable && id == sb->getUniversalId()))
{ {
sb->setFocus(); sb->setFocus();
if (!hint.empty())
sb->useHint (hint);
return; return;
} }
} }
@ -511,8 +517,6 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
assert(view); assert(view);
view->setParent(this); view->setParent(this);
mSubViews.append(view); // only after assert mSubViews.append(view); // only after assert
if (!hint.empty())
view->useHint (hint);
int minWidth = userSettings.setting ("window/minimum-width", QString("325")).toInt(); int minWidth = userSettings.setting ("window/minimum-width", QString("325")).toInt();
view->setMinimumWidth(minWidth); view->setMinimumWidth(minWidth);
@ -534,6 +538,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
this, SLOT (updateSubViewIndicies (SubView *))); this, SLOT (updateSubViewIndicies (SubView *)));
view->show(); view->show();
if (!hint.empty())
view->useHint (hint);
} }
void CSVDoc::View::newView() void CSVDoc::View::newView()
@ -716,6 +723,11 @@ void CSVDoc::View::addPathgridSubView()
addSubView (CSMWorld::UniversalId::Type_Pathgrids); addSubView (CSMWorld::UniversalId::Type_Pathgrids);
} }
void CSVDoc::View::addStartScriptsSubView()
{
addSubView (CSMWorld::UniversalId::Type_StartScripts);
}
void CSVDoc::View::abortOperation (int type) void CSVDoc::View::abortOperation (int type)
{ {
mDocument->abortOperation (type); mDocument->abortOperation (type);

View file

@ -215,6 +215,8 @@ namespace CSVDoc
void addPathgridSubView(); void addPathgridSubView();
void addStartScriptsSubView();
void toggleShowStatusBar (bool show); void toggleShowStatusBar (bool show);
void loadErrorLog(); void loadErrorLog();

View file

@ -248,7 +248,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
QMessageBox messageBox(view); QMessageBox messageBox(view);
CSMDoc::Document *document = view->getDocument(); 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.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?"); messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);

View file

@ -76,7 +76,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
if (landIndex != -1) if (landIndex != -1)
{ {
const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get(); 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, mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true,
Terrain::Align_XY)); Terrain::Align_XY));

View file

@ -22,7 +22,7 @@ namespace Resource
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
class CellRef; struct CellRef;
} }
namespace CSVWorld namespace CSVWorld

View file

@ -30,7 +30,7 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event)
void CSVTools::ReportTable::mouseMoveEvent (QMouseEvent *event) void CSVTools::ReportTable::mouseMoveEvent (QMouseEvent *event)
{ {
if (event->buttons() & Qt::LeftButton) if (event->buttons() & Qt::LeftButton)
startDrag (*this); startDragFromTable (*this);
} }
void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event)

View file

@ -2,6 +2,7 @@
#include <utility> #include <utility>
#include <memory> #include <memory>
#include <stdexcept>
#include <QGridLayout> #include <QGridLayout>
#include <QLabel> #include <QLabel>
@ -39,8 +40,12 @@ QAbstractItemDelegate(parent),
mTable(table) 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<QLabel*>(editor);
if(!label)
return;
QVariant v = index.data(Qt::EditRole); QVariant v = index.data(Qt::EditRole);
if (!v.isValid()) if (!v.isValid())
{ {
@ -53,16 +58,17 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QMod
if (QVariant::String == v.type()) if (QVariant::String == v.type())
{ {
editor->setText(v.toString()); label->setText(v.toString());
} else //else we are facing enums }
else //else we are facing enums
{ {
int data = v.toInt(); int data = v.toInt();
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mTable->getColumnId (index.column())))); std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (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 //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, QWidget* CSVWorld::NotEditableSubDelegate::createEditor (QWidget *parent,
const QStyleOptionViewItem& option, const QStyleOptionViewItem& option,
const QModelIndex& index, const QModelIndex& index) const
CSMWorld::ColumnBase::Display display) const
{ {
return new QLabel(parent); 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 void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{ {
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display)); std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
@ -257,7 +267,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
QWidget* editor = NULL; QWidget* editor = NULL;
if (! (mTable->flags (index) & Qt::ItemIsEditable)) if (! (mTable->flags (index) & Qt::ItemIsEditable))
{ {
return mNotEditableDelegate.createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display); return mNotEditableDelegate.createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index);
} }
std::map<int, CommandDelegate*>::iterator delegateIt(mDelegates.find(display)); std::map<int, CommandDelegate*>::iterator delegateIt(mDelegates.find(display));
@ -266,6 +276,8 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display); editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display); DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display);
// NOTE: For each entry in CSVWorld::CommandDelegate::createEditor() a corresponding entry
// is required here
if (qobject_cast<DropLineEdit*>(editor)) if (qobject_cast<DropLineEdit*>(editor))
{ {
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); 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())); connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
} }
else if (qobject_cast<QAbstractSpinBox*>(editor)) else if (qobject_cast<QAbstractSpinBox*>(editor) || qobject_cast<QLineEdit*>(editor))
{ {
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); 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))); 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 mProxys.push_back(proxy); //deleted in the destructor

View file

@ -40,9 +40,9 @@ namespace CSVWorld
public: public:
NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent = 0); 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; virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing ///< does nothing
@ -52,8 +52,7 @@ namespace CSVWorld
virtual QWidget *createEditor (QWidget *parent, virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option, const QStyleOptionViewItem& option,
const QModelIndex& index, const QModelIndex& index) const;
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
}; };
//this can't be nested into the DialogueDelegateDispatcher, because it needs to emit signals //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 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 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; virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;

View file

@ -3,7 +3,7 @@
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "dragrecordtable.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); CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument);

View file

@ -33,7 +33,7 @@ namespace CSVWorld
void setEditLock(bool locked); void setEditLock(bool locked);
protected: protected:
void startDrag(const DragRecordTable& table); void startDragFromTable(const DragRecordTable& table);
void dragEnterEvent(QDragEnterEvent *event); void dragEnterEvent(QDragEnterEvent *event);

View file

@ -46,7 +46,6 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent,
const QModelIndex& index) const const QModelIndex& index) const
{ {
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None); return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None);
//overloading virtual functions is HARD
} }
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,

View file

@ -345,7 +345,7 @@ void CSVWorld::RegionMap::viewInTable()
void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event)
{ {
startDrag(*this); startDragFromTable(*this);
} }
std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const

View file

@ -68,6 +68,7 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint)
if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line)) if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line))
cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column); cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column);
mEditor->setFocus();
mEditor->setTextCursor (cursor); mEditor->setTextCursor (cursor);
} }
} }

View file

@ -43,6 +43,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_BodyParts, CSMWorld::UniversalId::Type_BodyParts,
CSMWorld::UniversalId::Type_SoundGens, CSMWorld::UniversalId::Type_SoundGens,
CSMWorld::UniversalId::Type_Pathgrids, CSMWorld::UniversalId::Type_Pathgrids,
CSMWorld::UniversalId::Type_StartScripts,
CSMWorld::UniversalId::Type_None // end marker CSMWorld::UniversalId::Type_None // end marker
}; };
@ -123,6 +124,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_BodyPart, CSMWorld::UniversalId::Type_BodyPart,
CSMWorld::UniversalId::Type_SoundGen, CSMWorld::UniversalId::Type_SoundGen,
CSMWorld::UniversalId::Type_Pathgrid, CSMWorld::UniversalId::Type_Pathgrid,
CSMWorld::UniversalId::Type_StartScript,
CSMWorld::UniversalId::Type_None // end marker CSMWorld::UniversalId::Type_None // end marker
}; };

View file

@ -635,7 +635,7 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
{ {
if (event->buttons() & Qt::LeftButton) if (event->buttons() & Qt::LeftButton)
{ {
startDrag(*this); startDragFromTable(*this);
} }
} }

View file

@ -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. ///< \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, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index, CSMWorld::ColumnBase::Display display) const 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) switch (display)
{ {
case CSMWorld::ColumnBase::Display_Colour: case CSMWorld::ColumnBase::Display_Colour:
@ -228,6 +236,11 @@ bool CSVWorld::CommandDelegate::isEditLocked() const
return mEditLock; 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 void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const
{ {
QVariant v = index.data(Qt::EditRole); QVariant v = index.data(Qt::EditRole);

View file

@ -130,10 +130,14 @@ namespace CSVWorld
virtual void setModelData (QWidget *editor, QAbstractItemModel *model, virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const; const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent, virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option, const QStyleOptionViewItem& option,
const QModelIndex& index, const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const; CSMWorld::ColumnBase::Display display) const;
void setEditLock (bool locked); void setEditLock (bool locked);
@ -141,8 +145,9 @@ namespace CSVWorld
///< \return Does column require update? ///< \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: public slots:

View file

@ -7,6 +7,7 @@ set(GAME
) )
if (ANDROID) if (ANDROID)
set(GAME ${GAME} android_commandLine.cpp)
set(GAME ${GAME} android_main.c) set(GAME ${GAME} android_main.c)
endif() endif()
@ -104,7 +105,6 @@ find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
if (NOT ANDROID) if (NOT ANDROID)
add_executable(openmw add_executable(openmw
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
${OPENMW_FILES} ${OPENMW_FILES}
${GAME} ${GAME_HEADER} ${GAME} ${GAME_HEADER}
${APPLE_BUNDLE_RESOURCES} ${APPLE_BUNDLE_RESOURCES}
@ -112,7 +112,6 @@ if (NOT ANDROID)
else () else ()
add_library(openmw add_library(openmw
SHARED SHARED
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
${OPENMW_FILES} ${OPENMW_FILES}
${GAME} ${GAME_HEADER} ${GAME} ${GAME_HEADER}
) )
@ -120,9 +119,10 @@ endif ()
# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
# when we change the backend. # when we change the backend.
include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS}) include_directories(${SOUND_INPUT_INCLUDES})
target_link_libraries(openmw target_link_libraries(openmw
${OENGINE_LIBRARY}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS} ${OGRE_STATIC_PLUGINS}
${SHINY_LIBRARIES} ${SHINY_LIBRARIES}

View file

@ -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);
}

View file

@ -0,0 +1,16 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#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

View file

@ -1,10 +1,8 @@
#include "../../SDL_internal.h" #include "../../SDL_internal.h"
#ifdef __ANDROID__ #ifdef __ANDROID__
#include "SDL_main.h" #include "SDL_main.h"
/******************************************************************************* /*******************************************************************************
Functions called by JNI Functions called by JNI
*******************************************************************************/ *******************************************************************************/
@ -12,27 +10,24 @@
/* Called before to initialize JNI bindings */ /* Called before to initialize JNI bindings */
extern void SDL_Android_Init(JNIEnv* env, jclass cls); 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,
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) jobject obj) {
{
SDL_Android_Init(env, cls); SDL_Android_Init(env, cls);
SDL_SetMainReady(); SDL_SetMainReady();
/* Run the application code! */ /* Run the application code! */
int status; int status;
char *argv[2];
argv[0] = SDL_strdup("openmw");
argv[1] = NULL;
status = main(1, argv);
status = main(argcData+1, argvData);
releaseArgv();
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
/* exit(status); */ /* exit(status); */

View file

@ -10,6 +10,8 @@
#include <SDL.h> #include <SDL.h>
#include <openengine/misc/rng.hpp>
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/bsa/resources.hpp> #include <components/bsa/resources.hpp>
@ -191,15 +193,13 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mExportFonts(false) , mExportFonts(false)
, mNewGame (false) , mNewGame (false)
{ {
std::srand ( std::time(NULL) ); OEngine::Misc::Rng::init();
std::srand ( static_cast<unsigned int>(std::time(NULL)) );
MWClass::registerClasses(); 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) 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(); SDL_SetMainReady();
if(SDL_Init(flags) != 0) 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 // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // 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); 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); mEnvironment.setInputManager (input);
MWGui::WindowManager* window = new MWGui::WindowManager( MWGui::WindowManager* window = new MWGui::WindowManager(

View file

@ -290,7 +290,7 @@ public:
std::streamsize write(const char *str, std::streamsize size) std::streamsize write(const char *str, std::streamsize size)
{ {
// Make a copy for null termination // Make a copy for null termination
std::string tmp (str, size); std::string tmp (str, static_cast<unsigned int>(size));
// Write string to Visual Studio Debug output // Write string to Visual Studio Debug output
OutputDebugString (tmp.c_str ()); OutputDebugString (tmp.c_str ());
return size; return size;

View file

@ -37,11 +37,23 @@ namespace MWBase
virtual bool getControlSwitch (const std::string& sw) = 0; virtual bool getControlSwitch (const std::string& sw) = 0;
virtual std::string getActionDescription (int action) = 0; virtual std::string getActionDescription (int action) = 0;
virtual std::string getActionBindingName (int action) = 0; virtual std::string getActionKeyBindingName (int action) = 0;
virtual std::vector<int> getActionSorting () = 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<int> getActionKeySorting() = 0;
///Actions available for binding to controller buttons
virtual std::vector<int> getActionControllerSorting() = 0;
virtual int getNumActions() = 0; virtual int getNumActions() = 0;
virtual void enableDetectingBindingMode (int action) = 0; ///If keyboard is true, only pay attention to keyboard events. If false, only pay attention to controller events (excluding esc)
virtual void resetToDefaultBindings() = 0; 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;
}; };
} }

View file

@ -20,7 +20,7 @@ namespace MWWorld
namespace MWSound namespace MWSound
{ {
class Sound; class Sound;
class Sound_Decoder; struct Sound_Decoder;
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr; typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
} }

View file

@ -149,17 +149,14 @@ namespace MWBase
/// \todo investigate, if we really need to expose every single lousy UI element to the outside world /// \todo investigate, if we really need to expose every single lousy UI element to the outside world
virtual MWGui::DialogueWindow* getDialogueWindow() = 0; virtual MWGui::DialogueWindow* getDialogueWindow() = 0;
virtual MWGui::ContainerWindow* getContainerWindow() = 0;
virtual MWGui::InventoryWindow* getInventoryWindow() = 0; virtual MWGui::InventoryWindow* getInventoryWindow() = 0;
virtual MWGui::BookWindow* getBookWindow() = 0;
virtual MWGui::ScrollWindow* getScrollWindow() = 0;
virtual MWGui::CountDialog* getCountDialog() = 0; virtual MWGui::CountDialog* getCountDialog() = 0;
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0; virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
virtual MWGui::TradeWindow* getTradeWindow() = 0; virtual MWGui::TradeWindow* getTradeWindow() = 0;
virtual MWGui::SpellBuyingWindow* getSpellBuyingWindow() = 0;
virtual MWGui::TravelWindow* getTravelWindow() = 0; virtual void updateSpellWindow() = 0;
virtual MWGui::SpellWindow* getSpellWindow() = 0;
virtual MWGui::Console* getConsole() = 0; virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 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; virtual void configureSkills (const SkillList& major, const SkillList& minor) = 0;
///< configure skill groups, each set contains the skill ID for that group. ///< 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; virtual void updateSkillArea() = 0;
///< update display of skills, factions, birth sign, reputation and bounty ///< 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 startTraining(MWWorld::Ptr actor) = 0;
virtual void startRepair(MWWorld::Ptr actor) = 0; virtual void startRepair(MWWorld::Ptr actor) = 0;
virtual void startRepairItem(MWWorld::Ptr item) = 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; virtual void showSoulgemDialog (MWWorld::Ptr item) = 0;
@ -332,9 +329,8 @@ namespace MWBase
/// Does the current stack of GUI-windows permit saving? /// Does the current stack of GUI-windows permit saving?
virtual bool isSavingAllowed() const = 0; virtual bool isSavingAllowed() const = 0;
/// Returns the current Modal /// Send exit command to active Modal window
/** Used to send exit command to active Modal when Esc is pressed **/ virtual void exitCurrentModal() = 0;
virtual MWGui::WindowModal* getCurrentModal() const = 0;
/// Sets the current Modal /// Sets the current Modal
/** Used to send exit command to active Modal when Esc is pressed **/ /** Used to send exit command to active Modal when Esc is pressed **/

View file

@ -49,7 +49,7 @@ namespace MWRender
namespace MWMechanics namespace MWMechanics
{ {
class Movement; struct Movement;
} }
namespace MWWorld namespace MWWorld
@ -205,10 +205,8 @@ namespace MWBase
///< Return a pointer to a liveCellRef which contains \a ptr. ///< Return a pointer to a liveCellRef which contains \a ptr.
/// \note Search is limited to the active cells. /// \note Search is limited to the active cells.
/// \todo enable reference in the OGRE scene
virtual void enable (const MWWorld::Ptr& ptr) = 0; 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 disable (const MWWorld::Ptr& ptr) = 0;
virtual void advanceTime (double hours) = 0; virtual void advanceTime (double hours) = 0;
@ -268,6 +266,8 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0; virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range ///< Return pointer to the object the player is looking at, if it is within activation range
virtual float getMaxActivationDistance() = 0;
/// Returns a pointer to the object the provided object would hit (if within the /// Returns a pointer to the object the provided object would hit (if within the
/// specified distance), and the point where the hit occurs. This will attempt to /// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis. /// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
@ -551,7 +551,7 @@ namespace MWBase
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0; virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0;
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, int rangeType, const std::string& id, const std::string& sourceName) = 0; const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;

View file

@ -155,7 +155,7 @@ namespace MWClass
bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const 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 float Apparatus::getWeight(const MWWorld::Ptr &ptr) const

View file

@ -154,9 +154,9 @@ namespace MWClass
const MWWorld::Store<ESM::GameSetting> &gmst = const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
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) if (ref->mBase->mData.mWeight == 0)
return ESM::Skill::Unarmored; return ESM::Skill::Unarmored;
@ -245,7 +245,8 @@ namespace MWClass
else else
typeText = "#{sHeavy}"; 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); int remainingHealth = getItemHealth(ptr);
text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/"
@ -261,7 +262,7 @@ namespace MWClass
info.enchant = ref->mBase->mEnchant; info.enchant = ref->mBase->mEnchant;
if (!info.enchant.empty()) if (!info.enchant.empty())
info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); info.remainingEnchantCharge = static_cast<int>(ptr.getCellRef().getEnchantmentCharge());
info.text = text; info.text = text;
@ -290,6 +291,22 @@ namespace MWClass
return record->mId; return record->mId;
} }
int Armor::getEffectiveArmorRating(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const
{
MWWorld::LiveCellRef<ESM::Armor> *ref = ptr.get<ESM::Armor>();
int armorSkillType = getEquipmentSkill(ptr);
int armorSkill = actor.getClass().getSkill(actor, armorSkillType);
const MWBase::World *world = MWBase::Environment::get().getWorld();
int iBaseArmorSkill = world->getStore().get<ESM::GameSetting>().find("iBaseArmorSkill")->getInt();
if(ref->mBase->mData.mWeight == 0)
return ref->mBase->mData.mArmor;
else
return ref->mBase->mData.mArmor * armorSkill / iBaseArmorSkill;
}
std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
{ {
MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc);

View file

@ -86,6 +86,9 @@ namespace MWClass
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const; virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) 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;
}; };
} }

View file

@ -203,7 +203,7 @@ namespace MWClass
info.enchant = ref->mBase->mEnchant; info.enchant = ref->mBase->mEnchant;
if (!info.enchant.empty()) if (!info.enchant.empty())
info.remainingEnchantCharge = ptr.getCellRef().getEnchantmentCharge(); info.remainingEnchantCharge = static_cast<int>(ptr.getCellRef().getEnchantmentCharge());
info.text = text; info.text = text;

View file

@ -1,6 +1,8 @@
#include "creature.hpp" #include "creature.hpp"
#include <openengine/misc/rng.hpp>
#include <components/esm/loadcrea.hpp> #include <components/esm/loadcrea.hpp>
#include <components/esm/creaturestate.hpp> #include <components/esm/creaturestate.hpp>
@ -103,9 +105,9 @@ namespace MWClass
data->mCreatureStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mData.mEndurance); 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::Personality, ref->mBase->mData.mPersonality);
data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck); data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck);
data->mCreatureStats.setHealth (ref->mBase->mData.mHealth); data->mCreatureStats.setHealth(static_cast<float>(ref->mBase->mData.mHealth));
data->mCreatureStats.setMagicka (ref->mBase->mData.mMana); data->mCreatureStats.setMagicka(static_cast<float>(ref->mBase->mData.mMana));
data->mCreatureStats.setFatigue (ref->mBase->mData.mFatigue); data->mCreatureStats.setFatigue(static_cast<float>(ref->mBase->mData.mFatigue));
data->mCreatureStats.setLevel(ref->mBase->mData.mLevel); data->mCreatureStats.setLevel(ref->mBase->mData.mLevel);
@ -164,7 +166,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
MWRender::Actors& actors = renderingInterface.getActors(); 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 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); 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); victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
@ -288,9 +290,7 @@ namespace MWClass
if(attack) if(attack)
{ {
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
damage *= gmst.find("fDamageStrengthBase")->getFloat() + MWMechanics::adjustWeaponDamage(damage, weapon, ptr);
(stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.find("fDamageStrengthMult")->getFloat() * 0.1);
MWMechanics::adjustWeaponDamage(damage, weapon);
MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr); MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr);
} }
@ -355,7 +355,7 @@ namespace MWClass
if(!object.isEmpty()) if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); 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<ESM::Creature>()->mBase->mScript; const std::string &script = ptr.get<ESM::Creature>()->mBase->mScript;
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
@ -376,9 +376,8 @@ namespace MWClass
// Check for knockdown // Check for knockdown
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat(); float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
* getGmst().iKnockDownOddsMult->getInt() * 0.01 + getGmst().iKnockDownOddsBase->getInt(); * getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99())
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
{ {
getCreatureStats(ptr).setKnockedDown(true); getCreatureStats(ptr).setKnockedDown(true);
@ -493,7 +492,7 @@ namespace MWClass
{ {
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
return (ref->mBase->mFlags & ESM::Creature::Weapon); return (ref->mBase->mFlags & ESM::Creature::Weapon) != 0;
} }
std::string Creature::getScript (const MWWorld::Ptr& ptr) const std::string Creature::getScript (const MWWorld::Ptr& ptr) const
@ -508,7 +507,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref = MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>(); ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Essential; return (ref->mBase->mFlags & ESM::Creature::Essential) != 0;
} }
void Creature::registerSelf() void Creature::registerSelf()
@ -528,7 +527,7 @@ namespace MWClass
MWMechanics::CreatureStats& stats = getCreatureStats(ptr); MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
const GMST& gmst = getGmst(); 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()); * (gmst.fMaxWalkSpeedCreature->getFloat() - gmst.fMinWalkSpeedCreature->getFloat());
const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWBase::World *world = MWBase::Environment::get().getWorld();
@ -626,7 +625,7 @@ namespace MWClass
float Creature::getCapacity (const MWWorld::Ptr& ptr) const float Creature::getCapacity (const MWWorld::Ptr& ptr) const
{ {
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
return stats.getAttribute(0).getModified()*5; return static_cast<float>(stats.getAttribute(0).getModified() * 5);
} }
float Creature::getEncumbrance (const MWWorld::Ptr& ptr) const float Creature::getEncumbrance (const MWWorld::Ptr& ptr) const
@ -682,7 +681,7 @@ namespace MWClass
++sound; ++sound;
} }
if(!sounds.empty()) 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) if (type == ESM::SoundGenerator::Land)
@ -713,7 +712,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref = MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>(); ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Flies; return (ref->mBase->mFlags & ESM::Creature::Flies) != 0;
} }
bool Creature::canSwim(const MWWorld::Ptr &ptr) const bool Creature::canSwim(const MWWorld::Ptr &ptr) const

View file

@ -167,19 +167,19 @@ namespace MWClass
if (opening) if (opening)
{ {
MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
closeSound, 0.5); closeSound, 0.5f);
float offset = ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0; float offset = ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265f * 2.0f;
action->setSoundOffset(offset); action->setSoundOffset(offset);
action->setSound(openSound); action->setSound(openSound);
} }
else else
{ {
MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr, MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
openSound, 0.5); openSound, 0.5f);
float offset = 1.0 - ptr.getRefData().getLocalRotation().rot[2]/ 3.14159265 * 2.0; 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, //most if not all door have closing bang somewhere in the middle of the sound,
//so we divide offset by two //so we divide offset by two
action->setSoundOffset(offset * 0.5); action->setSoundOffset(offset * 0.5f);
action->setSound(closeSound); action->setSound(closeSound);
} }

View file

@ -192,7 +192,7 @@ namespace MWClass
bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const
{ {
return npcServices & ESM::NPC::Ingredients; return (npcServices & ESM::NPC::Ingredients) != 0;
} }

View file

@ -50,7 +50,7 @@ namespace MWClass
assert (ref->mBase != NULL); assert (ref->mBase != NULL);
if(!model.empty()) 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)) 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, MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0,
@ -205,7 +205,7 @@ namespace MWClass
{ {
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>(); MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
if (ptr.getCellRef().getCharge() == -1) if (ptr.getCellRef().getCharge() == -1)
return ref->mBase->mData.mTime; return static_cast<float>(ref->mBase->mData.mTime);
else else
return ptr.getCellRef().getChargeFloat(); return ptr.getCellRef().getChargeFloat();
} }
@ -221,7 +221,7 @@ namespace MWClass
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const 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 float Light::getWeight(const MWWorld::Ptr &ptr) const

View file

@ -173,7 +173,7 @@ namespace MWClass
bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const 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 int Lockpick::getItemMaxHealth (const MWWorld::Ptr& ptr) const

View file

@ -259,7 +259,7 @@ namespace MWClass
{ {
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>(); ptr.get<ESM::Miscellaneous>();
return ref->mBase->mData.mIsKey; return ref->mBase->mData.mIsKey != 0;
} }
} }

View file

@ -5,6 +5,8 @@
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <openengine/misc/rng.hpp>
#include <components/esm/loadmgef.hpp> #include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp> #include <components/esm/loadnpc.hpp>
#include <components/esm/npcstate.hpp> #include <components/esm/npcstate.hpp>
@ -66,12 +68,12 @@ namespace
double i = floor(d); double i = floor(d);
d -= i; d -= i;
if(d < 0.5) if(d < 0.5)
return i; return static_cast<int>(i);
if(d > 0.5) if(d > 0.5)
return i + 1.0; return static_cast<int>(i) + 1;
if(is_even(i)) if(is_even(i))
return i; return static_cast<int>(i);
return i + 1.0; return static_cast<int>(i) + 1;
} }
void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats) void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
@ -116,7 +118,7 @@ namespace
continue; continue;
// is this a minor or major skill? // is this a minor or major skill?
float add=0.2; float add=0.2f;
for (int k=0; k<5; ++k) for (int k=0; k<5; ++k)
{ {
if (class_->mData.mSkills[k][0] == j) if (class_->mData.mSkills[k][0] == j)
@ -149,7 +151,7 @@ namespace
|| class_->mData.mAttribute[1] == ESM::Attribute::Endurance) || class_->mData.mAttribute[1] == ESM::Attribute::Endurance)
multiplier += 1; multiplier += 1;
creatureStats.setHealth(static_cast<int> (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.fKnockDownMult = store.find("fKnockDownMult");
gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult"); gmst.iKnockDownOddsMult = store.find("iKnockDownOddsMult");
gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase"); gmst.iKnockDownOddsBase = store.find("iKnockDownOddsBase");
gmst.fDamageStrengthBase = store.find("fDamageStrengthBase");
gmst.fDamageStrengthMult = store.find("fDamageStrengthMult");
gmst.fCombatArmorMinMult = store.find("fCombatArmorMinMult"); gmst.fCombatArmorMinMult = store.find("fCombatArmorMinMult");
inited = true; inited = true;
@ -475,7 +475,6 @@ namespace MWClass
void Npc::hit(const MWWorld::Ptr& ptr, int type) const void Npc::hit(const MWWorld::Ptr& ptr, int type) const
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
const GMST& gmst = getGmst();
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
@ -507,7 +506,7 @@ namespace MWClass
if(otherstats.isDead()) // Can't hit dead actors if(otherstats.isDead()) // Can't hit dead actors
return; return;
if(ptr.getRefData().getHandle() == "player") if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->setEnemy(victim); MWBase::Environment::get().getWindowManager()->setEnemy(victim);
int weapskill = ESM::Skill::HandToHand; int weapskill = ESM::Skill::HandToHand;
@ -516,7 +515,7 @@ namespace MWClass
float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill)); 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); othercls.onHit(victim, 0.0f, false, weapon, ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
@ -538,10 +537,8 @@ namespace MWClass
if(attack) if(attack)
{ {
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); 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); MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr);
healthdmg = true; healthdmg = true;
} }
@ -549,7 +546,7 @@ namespace MWClass
{ {
MWMechanics::getHandToHandDamage(ptr, victim, damage, healthdmg); MWMechanics::getHandToHandDamage(ptr, victim, damage, healthdmg);
} }
if(ptr.getRefData().getHandle() == "player") if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
{ {
skillUsageSucceeded(ptr, weapskill, 0); skillUsageSucceeded(ptr, weapskill, 0);
@ -625,7 +622,7 @@ namespace MWClass
if(!object.isEmpty()) if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object)); 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); const std::string &script = ptr.getClass().getScript(ptr);
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */ /* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
@ -648,8 +645,7 @@ namespace MWClass
const GMST& gmst = getGmst(); const GMST& gmst = getGmst();
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt(); int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] if (OEngine::Misc::Rng::roll0to99() < chance)
if (roll < chance)
{ {
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
} }
@ -657,9 +653,8 @@ namespace MWClass
// Check for knockdown // Check for knockdown
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat(); float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat();
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
* gmst.iKnockDownOddsMult->getInt() * 0.01 + gmst.iKnockDownOddsBase->getInt(); * gmst.iKnockDownOddsMult->getInt() * 0.01f + gmst.iKnockDownOddsBase->getInt();
roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99())
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
{ {
getCreatureStats(ptr).setKnockedDown(true); getCreatureStats(ptr).setKnockedDown(true);
@ -685,12 +680,12 @@ namespace MWClass
MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron,
MWWorld::InventoryStore::Slot_LeftGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet 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 unmitigatedDamage = damage;
float x = damage / (damage + getArmorRating(ptr)); float x = damage / (damage + getArmorRating(ptr));
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x); damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
int damageDiff = unmitigatedDamage - damage; int damageDiff = static_cast<int>(unmitigatedDamage - damage);
if (damage < 1) if (damage < 1)
damage = 1; damage = 1;
@ -708,7 +703,7 @@ namespace MWClass
if (armorhealth == 0) if (armorhealth == 0)
armor = *inv.unequipItem(armor, ptr); armor = *inv.unequipItem(armor, ptr);
if (ptr.getRefData().getHandle() == "player") if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0); skillUsageSucceeded(ptr, armor.getClass().getEquipmentSkill(armor), 0);
switch(armor.getClass().getEquipmentSkill(armor)) switch(armor.getClass().getEquipmentSkill(armor))
@ -724,7 +719,7 @@ namespace MWClass
break; break;
} }
} }
else if(ptr.getRefData().getHandle() == "player") else if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
skillUsageSucceeded(ptr, ESM::Skill::Unarmored, 0); skillUsageSucceeded(ptr, ESM::Skill::Unarmored, 0);
} }
} }
@ -737,7 +732,7 @@ namespace MWClass
if(damage > 0.0f) if(damage > 0.0f)
{ {
sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.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(); MWBase::Environment::get().getWindowManager()->activateHitOverlay();
} }
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
@ -815,7 +810,7 @@ namespace MWClass
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
// player got activated by another NPC // player got activated by another NPC
if(ptr.getRefData().getHandle() == "player") if(ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(actor)); return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(actor));
// Werewolfs can't activate NPCs // Werewolfs can't activate NPCs
@ -938,7 +933,7 @@ namespace MWClass
gmst.fJumpEncumbranceMultiplier->getFloat() * gmst.fJumpEncumbranceMultiplier->getFloat() *
(1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr)); (1.0f - Npc::getEncumbrance(ptr)/Npc::getCapacity(ptr));
float a = npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified(); float a = static_cast<float>(npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified());
float b = 0.0f; float b = 0.0f;
if(a > 50.0f) if(a > 50.0f)
{ {
@ -993,7 +988,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::NPC> *ref = MWWorld::LiveCellRef<ESM::NPC> *ref =
ptr.get<ESM::NPC>(); ptr.get<ESM::NPC>();
return ref->mBase->mFlags & ESM::NPC::Essential; return (ref->mBase->mFlags & ESM::NPC::Essential) != 0;
} }
void Npc::registerSelf() void Npc::registerSelf()
@ -1086,7 +1081,6 @@ namespace MWClass
MWMechanics::NpcStats &stats = getNpcStats(ptr); MWMechanics::NpcStats &stats = getNpcStats(ptr);
MWWorld::InventoryStore &invStore = getInventoryStore(ptr); MWWorld::InventoryStore &invStore = getInventoryStore(ptr);
int iBaseArmorSkill = store.find("iBaseArmorSkill")->getInt();
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat(); float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat(); float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified(); int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
@ -1098,19 +1092,11 @@ namespace MWClass
if (it == invStore.end() || it->getTypeName() != typeid(ESM::Armor).name()) if (it == invStore.end() || it->getTypeName() != typeid(ESM::Armor).name())
{ {
// unarmored // unarmored
ratings[i] = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill); ratings[i] = static_cast<int>((fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill));
} }
else else
{ {
MWWorld::LiveCellRef<ESM::Armor> *ref = it->get<ESM::Armor>(); ratings[i] = it->getClass().getEffectiveArmorRating(*it, ptr);
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;
} }
} }

View file

@ -5,7 +5,7 @@
namespace ESM namespace ESM
{ {
class GameSetting; struct GameSetting;
} }
namespace MWClass namespace MWClass
@ -38,8 +38,6 @@ namespace MWClass
const ESM::GameSetting *fKnockDownMult; const ESM::GameSetting *fKnockDownMult;
const ESM::GameSetting *iKnockDownOddsMult; const ESM::GameSetting *iKnockDownOddsMult;
const ESM::GameSetting *iKnockDownOddsBase; const ESM::GameSetting *iKnockDownOddsBase;
const ESM::GameSetting *fDamageStrengthBase;
const ESM::GameSetting *fDamageStrengthMult;
const ESM::GameSetting *fCombatArmorMinMult; const ESM::GameSetting *fCombatArmorMinMult;
}; };

View file

@ -185,7 +185,7 @@ namespace MWClass
bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const 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 float Potion::getWeight(const MWWorld::Ptr &ptr) const

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