Add OpenMW commits up to 1 Jan 2019

# Conflicts:
#	.travis.yml
#	CMakeLists.txt
#	apps/openmw/mwbase/world.hpp
#	apps/openmw/mwphysics/physicssystem.hpp
#	apps/openmw/mwworld/worldimp.cpp
#	apps/openmw/mwworld/worldimp.hpp
pull/541/head
David Cernat 5 years ago
commit 6fdef4fd0a

1
.gitignore vendored

@ -82,5 +82,4 @@ moc_*.cxx
*ui_playpage.h
*.[ao]
*.so
openmw.appdata.xml
venv/

@ -15,8 +15,8 @@ Debian:
- apt-get update -yq
- apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt4-dev libopenal-dev libopenscenegraph-3.4-dev libunshield-dev libtinyxml-dev
# - apt-get install -y libmygui-dev libbullet-dev # to be updated to latest below because stretch is too old
- curl -L http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet-dev_2.87+dfsg-2_amd64.deb -o libbullet-dev_2.87+dfsg-2_amd64.deb
- curl -L http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet2.87_2.87+dfsg-2_amd64.deb -o libbullet2.87_2.87+dfsg-2_amd64.deb
- curl -L http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet-dev_2.87+dfsg-3_amd64.deb -o libbullet-dev_2.87+dfsg-3_amd64.deb
- curl -L http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet2.87_2.87+dfsg-3_amd64.deb -o libbullet2.87_2.87+dfsg-3_amd64.deb
- curl -L https://http.kali.org/pool/main/m/mygui/libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb -o libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb
- curl -L https://http.kali.org/pool/main/m/mygui/libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb -o libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb
- curl -L https://http.kali.org/pool/main/m/mygui/libmygui-dev_3.2.2+dfsg-1_amd64.deb -o libmygui-dev_3.2.2+dfsg-1_amd64.deb

@ -72,6 +72,7 @@ script:
- cd ./build
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j3; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
#deploy:

@ -1,16 +1,24 @@
0.46.0
------
Bug #2987: Editor: some chance and AI data fields can overflow
Bug #3623: Fix HiDPI on Windows
Bug #4411: Reloading a saved game while falling prevents damage in some cases
Bug #4540: Rain delay when exiting water
Bug #4701: PrisonMarker record is not hardcoded like other markers
Bug #4714: Crash upon game load in the repair menu while the "Your repair failed!" message is active
Bug #4715: "Cannot get class of an empty object" exception after pressing ESC in the dialogue mode
Bug #4720: Inventory avatar has shield with two-handed weapon during [un]equipping animation
Bug #4723: ResetActors command works incorrectly
Bug #4745: Editor: Interior cell lighting field values are not displayed as colors
Bug #4746: Non-solid player can't run or sneak
Bug #4750: Sneaking doesn't work in first person view if the player is in attack ready state
Bug #4768: Fallback numerical value recovery chokes on invalid arguments
Feature #2229: Improve pathfinding AI
Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis
Feature #4673: Weapon sheathing
Feature #4730: Native animated containers support
Task #4686: Upgrade media decoder to a more current FFmpeg API
0.45.0

@ -1,10 +1,11 @@
#!/bin/sh -e
brew update
brew outdated cmake || brew upgrade cmake
brew unlink cmake || true
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/a3b64391ebace30b84de8e7997665a1621c0b2c0/Formula/cmake.rb
brew switch cmake 3.12.4
brew outdated pkgconfig || brew upgrade pkgconfig
brew install qt
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-7cf2789.zip -o ~/openmw-deps.zip
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-55c27b1.zip -o ~/openmw-deps.zip
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null

@ -31,6 +31,7 @@ SKIP_EXTRACT=""
KEEP=""
UNITY_BUILD=""
VS_VERSION=""
NMAKE=""
PLATFORM=""
CONFIGURATION=""
@ -66,6 +67,9 @@ while [ $# -gt 0 ]; do
VS_VERSION=$1
shift ;;
n )
NMAKE=true ;;
p )
PLATFORM=$1
shift ;;
@ -94,6 +98,8 @@ Options:
Configure for unity builds.
-v <2013/2015/2017>
Choose the Visual Studio version to use.
-n
Produce NMake makefiles instead of a Visual Studio solution.
-V
Run verbosely
EOF
@ -108,6 +114,10 @@ EOF
done
done
if [ -n "$NMAKE" ]; then
command -v nmake -? >/dev/null 2>&1 || { echo "Error: nmake (NMake) is not on the path. Make sure you have the necessary environment variables set for command-line C++ development (for example, by starting from a Developer Command Prompt)."; exit 1; }
fi
if [ -z $VERBOSE ]; then
STRIP="> /dev/null 2>&1"
fi
@ -267,18 +277,12 @@ case $PLATFORM in
ARCHNAME="x86-64"
ARCHSUFFIX="64"
BITS="64"
BASE_OPTS="-G\"$GENERATOR Win64\""
add_cmake_opts "-G\"$GENERATOR Win64\""
;;
x32|x86|i686|i386|win32|Win32 )
ARCHNAME="x86"
ARCHSUFFIX="86"
BITS="32"
BASE_OPTS="-G\"$GENERATOR\""
add_cmake_opts "-G\"$GENERATOR\""
;;
* )
@ -304,14 +308,24 @@ case $CONFIGURATION in
;;
esac
if ! [ -z $UNITY_BUILD ]; then
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
fi
if [ ${BITS} -eq 64 ]; then
GENERATOR="${GENERATOR} Win64"
fi
if [ -n "$NMAKE" ]; then
GENERATOR="NMake Makefiles"
fi
add_cmake_opts "-G\"$GENERATOR\""
if [ -n "$NMAKE" ]; then
add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}"
fi
if ! [ -z $UNITY_BUILD ]; then
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
fi
echo
echo "==================================="
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
@ -387,6 +401,11 @@ cd .. #/..
# Set up dependencies
BUILD_DIR="MSVC${MSVC_DISPLAY_YEAR}_${BITS}"
if [ -n "$NMAKE" ]; then
BUILD_DIR="${BUILD_DIR}_NMake_${BUILD_CONFIG}"
fi
if [ -z $KEEP ]; then
echo
echo "(Re)Creating build directory."
@ -696,7 +715,11 @@ fi
# NOTE: Disable this when/if we want to run test cases
#if [ -z $CI ]; then
echo "- Copying Runtime DLLs..."
mkdir -p $BUILD_CONFIG
DLL_PREFIX=""
if [ -z $NMAKE ]; then
mkdir -p $BUILD_CONFIG
DLL_PREFIX="$BUILD_CONFIG/"
fi
for DLL in $RUNTIME_DLLS; do
TARGET="$(basename "$DLL")"
if [[ "$DLL" == *":"* ]]; then
@ -705,21 +728,21 @@ fi
TARGET=${SPLIT[1]}
fi
echo " ${TARGET}."
cp "$DLL" "$BUILD_CONFIG/$TARGET"
cp "$DLL" "${DLL_PREFIX}$TARGET"
done
echo
echo "- OSG Plugin DLLs..."
mkdir -p $BUILD_CONFIG/osgPlugins-3.4.1
mkdir -p ${DLL_PREFIX}osgPlugins-3.4.1
for DLL in $OSG_PLUGINS; do
echo " $(basename $DLL)."
cp "$DLL" $BUILD_CONFIG/osgPlugins-3.4.1
cp "$DLL" ${DLL_PREFIX}osgPlugins-3.4.1
done
echo
echo "- Qt Platform DLLs..."
mkdir -p ${BUILD_CONFIG}/platforms
mkdir -p ${DLL_PREFIX}platforms
for DLL in $QT_PLATFORMS; do
echo " $(basename $DLL)"
cp "$DLL" "${BUILD_CONFIG}/platforms"
cp "$DLL" "${DLL_PREFIX}platforms"
done
echo
#fi

@ -11,7 +11,7 @@ cd build
cmake \
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \
-D CMAKE_OSX_SYSROOT="macosx10.13" \
-D CMAKE_OSX_SYSROOT="macosx10.14" \
-D CMAKE_BUILD_TYPE=Release \
-D OPENMW_OSX_DEPLOYMENT=TRUE \
-D DESIRED_QT_VERSION=5 \

@ -0,0 +1,15 @@
#!/usr/bin/env bash
hdiutil attach ./*.dmg -mountpoint "${TRAVIS_BUILD_DIR}/openmw-package" > /dev/null || echo "hdutil has failed"
EXPECTED_PACKAGE_FILES=('Applications' 'OpenMW-CS.app' 'OpenMW.app')
PACKAGE_FILES=$(ls "${TRAVIS_BUILD_DIR}/openmw-package" | LC_ALL=C sort)
DIFF=$(diff <(printf "%s\n" "${EXPECTED_PACKAGE_FILES[@]}") <(printf "%s\n" "${PACKAGE_FILES[@]}"))
DIFF_STATUS=$?
if [[ $DIFF_STATUS -ne 0 ]]; then
echo "The package should only contain an Applications symlink and two applications, see the following diff for details." >&2
echo "$DIFF" >&2
exit 1
fi

@ -62,6 +62,7 @@ set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "")
set(OPENMW_VERSION_COMMITDATE "")
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -74,6 +75,18 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
else(GIT_FOUND)
message(WARNING "Git executable not found")
endif(GIT_FOUND)
if(GIT_FOUND)
execute_process (
COMMAND ${GIT_EXECUTABLE} log -1 --format='%aI'
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE EXITCODE3
OUTPUT_VARIABLE OPENMW_VERSION_COMMITDATE
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT EXITCODE3)
string(SUBSTRING ${OPENMW_VERSION_COMMITDATE} 1 10 OPENMW_VERSION_COMMITDATE)
endif(NOT EXITCODE3)
endif(GIT_FOUND)
endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
# Macros
@ -266,8 +279,14 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
osgdb_tga
)
get_filename_component(OSG_LIB_DIR ${OSGDB_LIBRARY} DIRECTORY)
set(OSGPlugins_LIB_DIR "${OSG_LIB_DIR}/osgPlugins-${OPENSCENEGRAPH_VERSION}")
set(OSGPlugins_LIB_DIR "")
foreach(OSGDB_LIB ${OSGDB_LIBRARY})
# Skip library type names
if(EXISTS ${OSGDB_LIB} AND NOT IS_DIRECTORY ${OSGDB_LIB})
get_filename_component(OSG_LIB_DIR ${OSGDB_LIB} DIRECTORY)
list(APPEND OSGPlugins_LIB_DIR "${OSG_LIB_DIR}/osgPlugins-${OPENSCENEGRAPH_VERSION}")
endif()
endforeach(OSGDB_LIB)
if(OSG_STATIC)
add_definitions(-DOSG_LIBRARY_STATIC)
@ -366,6 +385,9 @@ configure_resource_file(${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp-server-default.
configure_resource_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
"${OpenMW_BINARY_DIR}" "settings-default.cfg")
configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
"${OpenMW_BINARY_DIR}" "openmw.appdata.xml")
if (NOT APPLE)
configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
"${OpenMW_BINARY_DIR}" "openmw.cfg")
@ -625,7 +647,7 @@ set(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Do not build RecastDemo")
set(RECASTNAVIGATION_STATIC ON CACHE BOOL "Build recastnavigation static libraries")
set(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Do not build recastnavigation tests")
add_subdirectory (extern/recastnavigation)
add_subdirectory (extern/recastnavigation EXCLUDE_FROM_ALL)
add_subdirectory (extern/osg-ffmpeg-videoplayer)
add_subdirectory (extern/oics)
if (BUILD_OPENCS)
@ -836,6 +858,10 @@ endif()
# Apple bundling
if (OPENMW_OSX_DEPLOYMENT AND APPLE AND DESIRED_QT_VERSION MATCHES 5)
if (${CMAKE_MAJOR_VERSION} STREQUAL "3" AND ${CMAKE_MINOR_VERSION} STREQUAL "13")
message(FATAL_ERROR "macOS packaging is broken in CMake 3.13.*, see https://gitlab.com/OpenMW/openmw/issues/4767. Please use an older version like 3.12.4")
endif ()
get_property(QT_COCOA_PLUGIN_PATH TARGET Qt5::QCocoaIntegrationPlugin PROPERTY LOCATION_RELEASE)
get_filename_component(QT_COCOA_PLUGIN_DIR "${QT_COCOA_PLUGIN_PATH}" DIRECTORY)
get_filename_component(QT_COCOA_PLUGIN_GROUP "${QT_COCOA_PLUGIN_DIR}" NAME)
@ -870,15 +896,24 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE AND DESIRED_QT_VERSION MATCHES 5)
set(ABSOLUTE_PLUGINS "")
set(OSGPlugins_DONT_FIND_DEPENDENCIES 1)
find_package(OSGPlugins REQUIRED COMPONENTS ${USED_OSG_PLUGINS})
foreach (PLUGIN_NAME ${USED_OSG_PLUGINS})
set(PLUGIN_ABS "${OSGPlugins_LIB_DIR}/${PLUGIN_NAME}.so")
set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS})
string(TOUPPER ${PLUGIN_NAME} PLUGIN_NAME_UC)
if(${PLUGIN_NAME_UC}_LIBRARY_RELEASE)
set(PLUGIN_ABS ${${PLUGIN_NAME_UC}_LIBRARY_RELEASE})
elseif(${PLUGIN_NAME_UC}_LIBRARY)
set(PLUGIN_ABS ${${PLUGIN_NAME_UC}_LIBRARY})
else()
message(FATAL_ERROR "Can't find library file for ${PLUGIN_NAME}")
# We used to construct the path manually from OSGPlugins_LIB_DIR and the plugin name.
# Maybe that could be restored as a fallback?
endif()
set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS})
endforeach ()
get_filename_component(OSG_PLUGIN_PREFIX_DIR "${OSGPlugins_LIB_DIR}" NAME)
if (NOT OSG_PLUGIN_PREFIX_DIR)
message(FATAL_ERROR "Can't get directory name for OSG plugins from '${OSGPlugins_LIB_DIR}'")
endif()
set(OSG_PLUGIN_PREFIX_DIR "osgPlugins-${OPENSCENEGRAPH_VERSION}")
# installs used plugins in bundle at given path (bundle_path must be relative to ${CMAKE_INSTALL_PREFIX})
# and returns list of install paths for all installed plugins

@ -406,13 +406,10 @@ int load(Arguments& info)
} catch(std::exception &e) {
std::cout << "\nERROR:\n\n " << e.what() << std::endl;
typedef std::deque<EsmTool::RecordBase *> RecStore;
RecStore &store = info.data.mRecords;
for (RecStore::iterator it = store.begin(); it != store.end(); ++it)
{
delete *it;
}
store.clear();
for (const EsmTool::RecordBase* record : info.data.mRecords)
delete record;
info.data.mRecords.clear();
return 1;
}
@ -444,15 +441,12 @@ int clone(Arguments& info)
std::cout << "Loaded " << recordCount << " records:" << std::endl << std::endl;
int i = 0;
typedef std::map<int, int> Stats;
Stats &stats = info.data.mRecordStats;
for (Stats::iterator it = stats.begin(); it != stats.end(); ++it)
for (std::pair<int, int> stat : info.data.mRecordStats)
{
ESM::NAME name;
name.intval = it->first;
int amount = it->second;
name.intval = stat.first;
int amount = stat.second;
std::cout << std::setw(digitCount) << amount << " " << name.toString() << " ";
if (++i % 3 == 0)
std::cout << std::endl;
}
@ -470,18 +464,18 @@ int clone(Arguments& info)
esm.setVersion(info.data.version);
esm.setRecordCount (recordCount);
for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
esm.addMaster(it->name, it->size);
for (const ESM::Header::MasterData &master : info.data.masters)
esm.addMaster(master.name, master.size);
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
esm.save(save);
int saved = 0;
typedef std::deque<EsmTool::RecordBase *> Records;
Records &records = info.data.mRecords;
for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it)
for (EsmTool::RecordBase* record : info.data.mRecords)
{
EsmTool::RecordBase *record = *it;
if (i <= 0)
break;
const ESM::NAME& typeName = record->getType();
esm.startRecord(typeName.toString(), record->getFlags());
@ -489,13 +483,10 @@ int clone(Arguments& info)
record->save(esm);
if (typeName.intval == ESM::REC_CELL) {
ESM::Cell *ptr = &record->cast<ESM::Cell>()->get();
if (!info.data.mCellRefs[ptr].empty()) {
typedef std::deque<std::pair<ESM::CellRef, bool> > RefList;
RefList &refs = info.data.mCellRefs[ptr];
for (RefList::iterator refIt = refs.begin(); refIt != refs.end(); ++refIt)
{
refIt->first.save(esm, refIt->second);
}
if (!info.data.mCellRefs[ptr].empty())
{
for (std::pair<ESM::CellRef, bool> &ref : info.data.mCellRefs[ptr])
ref.first.save(esm, ref.second);
}
}
@ -558,8 +549,5 @@ int comp(Arguments& info)
return 1;
}
return 0;
}

@ -651,7 +651,7 @@ std::string ruleFunction(int idx)
std::string bodyPartFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
@ -665,7 +665,7 @@ std::string bodyPartFlags(int flags)
std::string cellFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
if (flags & ESM::Cell::Interior) properties += "Interior ";
@ -686,7 +686,7 @@ std::string cellFlags(int flags)
std::string containerFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::Container::Unknown) properties += "Unknown ";
if (flags & ESM::Container::Organic) properties += "Organic ";
@ -702,7 +702,7 @@ std::string containerFlags(int flags)
std::string creatureFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::Creature::None) properties += "All ";
if (flags & ESM::Creature::Walks) properties += "Walks ";
@ -732,7 +732,7 @@ std::string creatureFlags(int flags)
std::string landFlags(int flags)
{
std::string properties = "";
std::string properties;
// The ESM component says that this first four bits are used, but
// only the first three bits are used as far as I can tell.
// There's also no enumeration of the bit in the ESM component.
@ -747,7 +747,7 @@ std::string landFlags(int flags)
std::string itemListFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::ItemLevList::AllLevels) properties += "AllLevels ";
if (flags & ESM::ItemLevList::Each) properties += "Each ";
@ -761,7 +761,7 @@ std::string itemListFlags(int flags)
std::string creatureListFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels ";
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
@ -800,7 +800,7 @@ std::string lightFlags(int flags)
std::string magicEffectFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::MagicEffect::TargetAttribute) properties += "TargetAttribute ";
if (flags & ESM::MagicEffect::TargetSkill) properties += "TargetSkill ";
@ -826,7 +826,7 @@ std::string magicEffectFlags(int flags)
std::string npcFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
// Mythicmods and the ESM component differ. Mythicmods says
// 0x8=None and 0x10=AutoCalc, while our code previously defined
@ -860,7 +860,7 @@ std::string npcFlags(int flags)
std::string raceFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
// All races have the playable flag set in Bethesda files.
if (flags & ESM::Race::Playable) properties += "Playable ";
@ -875,7 +875,7 @@ std::string raceFlags(int flags)
std::string spellFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
if (flags & ESM::Spell::F_Autocalc) properties += "Autocalc ";
if (flags & ESM::Spell::F_PCStart) properties += "PCStart ";
@ -891,7 +891,7 @@ std::string spellFlags(int flags)
std::string weaponFlags(int flags)
{
std::string properties = "";
std::string properties;
if (flags == 0) properties += "[None] ";
// The interpretation of the flags are still unclear to me.
// Apparently you can't be Silver without being Magical? Many of

@ -49,7 +49,7 @@ void printAIPackage(ESM::AIPackage p)
std::cout << " BadPackage: " << boost::format("0x%08x") % p.mType << std::endl;
}
if (p.mCellName != "")
if (!p.mCellName.empty())
std::cout << " Cell Name: " << p.mCellName << std::endl;
}
@ -130,43 +130,41 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
void printEffectList(ESM::EffectList effects)
{
int i = 0;
std::vector<ESM::ENAMstruct>::iterator eit;
for (eit = effects.mList.begin(); eit != effects.mList.end(); ++eit)
{
std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID)
<< " (" << eit->mEffectID << ")" << std::endl;
if (eit->mSkill != -1)
std::cout << " Skill: " << skillLabel(eit->mSkill)
<< " (" << (int)eit->mSkill << ")" << std::endl;
if (eit->mAttribute != -1)
std::cout << " Attribute: " << attributeLabel(eit->mAttribute)
<< " (" << (int)eit->mAttribute << ")" << std::endl;
std::cout << " Range: " << rangeTypeLabel(eit->mRange)
<< " (" << eit->mRange << ")" << std::endl;
for (const ESM::ENAMstruct& effect : effects.mList)
{
std::cout << " Effect[" << i << "]: " << magicEffectLabel(effect.mEffectID)
<< " (" << effect.mEffectID << ")" << std::endl;
if (effect.mSkill != -1)
std::cout << " Skill: " << skillLabel(effect.mSkill)
<< " (" << (int)effect.mSkill << ")" << std::endl;
if (effect.mAttribute != -1)
std::cout << " Attribute: " << attributeLabel(effect.mAttribute)
<< " (" << (int)effect.mAttribute << ")" << std::endl;
std::cout << " Range: " << rangeTypeLabel(effect.mRange)
<< " (" << effect.mRange << ")" << std::endl;
// Area is always zero if range type is "Self"
if (eit->mRange != ESM::RT_Self)
std::cout << " Area: " << eit->mArea << std::endl;
std::cout << " Duration: " << eit->mDuration << std::endl;
std::cout << " Magnitude: " << eit->mMagnMin << "-" << eit->mMagnMax << std::endl;
if (effect.mRange != ESM::RT_Self)
std::cout << " Area: " << effect.mArea << std::endl;
std::cout << " Duration: " << effect.mDuration << std::endl;
std::cout << " Magnitude: " << effect.mMagnMin << "-" << effect.mMagnMax << std::endl;
i++;
}
}
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)
for (const ESM::Transport::Dest& dest : transport)
{
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;
<< boost::format("%12.3f") % dest.mPos.pos[0] << ","
<< boost::format("%12.3f") % dest.mPos.pos[1] << ","
<< boost::format("%12.3f") % dest.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;
<< boost::format("%9.6f") % dest.mPos.rot[0] << ","
<< boost::format("%9.6f") % dest.mPos.rot[1] << ","
<< boost::format("%9.6f") % dest.mPos.rot[2] << ")" << std::endl;
if (!dest.mCellName.empty())
std::cout << " Destination Cell: " << dest.mCellName << std::endl;
}
}
@ -414,7 +412,7 @@ void Record<ESM::Potion>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -429,9 +427,9 @@ void Record<ESM::Armor>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
if (mData.mEnchant != "")
if (!mData.mEnchant.empty())
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
std::cout << " Type: " << armorTypeLabel(mData.mData.mType)
<< " (" << mData.mData.mType << ")" << std::endl;
@ -440,15 +438,15 @@ void Record<ESM::Armor>::print()
std::cout << " Health: " << mData.mData.mHealth << std::endl;
std::cout << " Armor: " << mData.mData.mArmor << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
for (const ESM::PartReference &part : mData.mParts.mParts)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
std::cout << " Male Name: " << pit->mMale << std::endl;
if (pit->mFemale != "")
std::cout << " Female Name: " << pit->mFemale << std::endl;
std::cout << " Body Part: " << bodyPartLabel(part.mPart)
<< " (" << (int)(part.mPart) << ")" << std::endl;
std::cout << " Male Name: " << part.mMale << std::endl;
if (!part.mFemale.empty())
std::cout << " Female Name: " << part.mFemale << std::endl;
}
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -487,9 +485,9 @@ void Record<ESM::Book>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
if (mData.mEnchant != "")
if (!mData.mEnchant.empty())
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -516,9 +514,8 @@ void Record<ESM::BirthSign>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl;
std::vector<std::string>::iterator pit;
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
std::cout << " Power: " << *pit << std::endl;
for (const std::string &power : mData.mPowers.mList)
std::cout << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -526,9 +523,9 @@ template<>
void Record<ESM::Cell>::print()
{
// None of the cells have names...
if (mData.mName != "")
if (!mData.mName.empty())
std::cout << " Name: " << mData.mName << std::endl;
if (mData.mRegion != "")
if (!mData.mRegion.empty())
std::cout << " Region: " << mData.mRegion << std::endl;
std::cout << " Flags: " << cellFlags(mData.mData.mFlags) << std::endl;
@ -580,23 +577,22 @@ void Record<ESM::Clothing>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
if (mData.mEnchant != "")
if (!mData.mEnchant.empty())
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
std::cout << " Type: " << clothingTypeLabel(mData.mData.mType)
<< " (" << mData.mData.mType << ")" << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
for (const ESM::PartReference &part : mData.mParts.mParts)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
std::cout << " Male Name: " << pit->mMale << std::endl;
if (pit->mFemale != "")
std::cout << " Female Name: " << pit->mFemale << std::endl;
std::cout << " Body Part: " << bodyPartLabel(part.mPart)
<< " (" << (int)(part.mPart) << ")" << std::endl;
std::cout << " Male Name: " << part.mMale << std::endl;
if (!part.mFemale.empty())
std::cout << " Female Name: " << part.mFemale << std::endl;
}
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -606,14 +602,13 @@ void Record<ESM::Container>::print()
{
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount
<< " Item: " << item.mItem.toString() << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -656,14 +651,12 @@ void Record<ESM::Creature>::print()
<< "-" << mData.mData.mAttack[5] << std::endl;
std::cout << " Gold: " << mData.mData.mGold << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount
<< " Item: " << item.mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
for (const std::string &spell : mData.mSpells.mList)
std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport());
@ -678,9 +671,8 @@ void Record<ESM::Creature>::print()
std::cout << " AI U4:" << (int)mData.mAiData.mU4 << std::endl;
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
printAIPackage(package);
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -693,9 +685,8 @@ void Record<ESM::Dialogue>::print()
// Sadly, there are no DialInfos, because the loader dumps as it
// loads, rather than loading and then dumping. :-( Anyone mind if
// I change this?
ESM::Dialogue::InfoContainer::iterator iit;
for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); ++iit)
std::cout << "INFO!" << iit->mId << std::endl;
for (const ESM::DialInfo &info : mData.mInfo)
std::cout << "INFO!" << info.mId << std::endl;
}
template<>
@ -735,7 +726,7 @@ void Record<ESM::Faction>::print()
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
for (int i = 0; i != 10; i++)
if (mData.mRanks[i] != "")
if (!mData.mRanks[i].empty())
{
std::cout << " Rank: " << mData.mRanks[i] << std::endl;
std::cout << " Attribute1 Requirement: "
@ -749,9 +740,8 @@ void Record<ESM::Faction>::print()
std::cout << " Faction Reaction: "
<< mData.mData.mRankData[i].mFactReaction << std::endl;
}
std::map<std::string, int>::iterator rit;
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); ++rit)
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
for (const std::pair<std::string, int> &reaction : mData.mReactions)
std::cout << " Reaction: " << reaction.second << " = " << reaction.first << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -772,34 +762,34 @@ template<>
void Record<ESM::DialInfo>::print()
{
std::cout << " Id: " << mData.mId << std::endl;
if (mData.mPrev != "")
if (!mData.mPrev.empty())
std::cout << " Previous ID: " << mData.mPrev << std::endl;
if (mData.mNext != "")
if (!mData.mNext.empty())
std::cout << " Next ID: " << mData.mNext << std::endl;
std::cout << " Text: " << mData.mResponse << std::endl;
if (mData.mActor != "")
if (!mData.mActor.empty())
std::cout << " Actor: " << mData.mActor << std::endl;
if (mData.mRace != "")
if (!mData.mRace.empty())
std::cout << " Race: " << mData.mRace << std::endl;
if (mData.mClass != "")
if (!mData.mClass.empty())
std::cout << " Class: " << mData.mClass << std::endl;
std::cout << " Factionless: " << mData.mFactionLess << std::endl;
if (mData.mFaction != "")
if (!mData.mFaction.empty())
std::cout << " NPC Faction: " << mData.mFaction << std::endl;
if (mData.mData.mRank != -1)
std::cout << " NPC Rank: " << (int)mData.mData.mRank << std::endl;
if (mData.mPcFaction != "")
if (!mData.mPcFaction.empty())
std::cout << " PC Faction: " << mData.mPcFaction << std::endl;
// CHANGE? non-standard capitalization mPCrank -> mPCRank (mPcRank?)
if (mData.mData.mPCrank != -1)
std::cout << " PC Rank: " << (int)mData.mData.mPCrank << std::endl;
if (mData.mCell != "")
if (!mData.mCell.empty())
std::cout << " Cell: " << mData.mCell << std::endl;
if (mData.mData.mDisposition > 0)
std::cout << " Disposition/Journal index: " << mData.mData.mDisposition << std::endl;
if (mData.mData.mGender != ESM::DialInfo::NA)
std::cout << " Gender: " << mData.mData.mGender << std::endl;
if (mData.mSound != "")
if (!mData.mSound.empty())
std::cout << " Sound File: " << mData.mSound << std::endl;
@ -808,11 +798,10 @@ void Record<ESM::DialInfo>::print()
std::cout << " Unknown1: " << mData.mData.mUnknown1 << std::endl;
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); ++sit)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
for (const ESM::DialInfo::SelectStruct &rule : mData.mSelects)
std::cout << " Select Rule: " << ruleString(rule) << std::endl;
if (mData.mResultScript != "")
if (!mData.mResultScript.empty())
{
if (mPrintPlain)
{
@ -835,7 +824,7 @@ void Record<ESM::Ingredient>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -877,10 +866,9 @@ void Record<ESM::CreatureLevList>::print()
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Creature: Level: " << iit->mLevel
<< " Creature: " << iit->mId << std::endl;
for (const ESM::LevelledListBase::LevelItem &item : mData.mList)
std::cout << " Creature: Level: " << item.mLevel
<< " Creature: " << item.mId << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -890,23 +878,22 @@ void Record<ESM::ItemLevList>::print()
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl;
for (const ESM::LevelledListBase::LevelItem &item : mData.mList)
std::cout << " Inventory: Level: " << item.mLevel
<< " Item: " << item.mId << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
template<>
void Record<ESM::Light>::print()
{
if (mData.mName != "")
if (!mData.mName.empty())
std::cout << " Name: " << mData.mName << std::endl;
if (mData.mModel != "")
if (!mData.mModel.empty())
std::cout << " Model: " << mData.mModel << std::endl;
if (mData.mIcon != "")
if (!mData.mIcon.empty())
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Flags: " << lightFlags(mData.mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
@ -924,7 +911,7 @@ void Record<ESM::Lockpick>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -939,7 +926,7 @@ void Record<ESM::Probe>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -954,7 +941,7 @@ void Record<ESM::Repair>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -981,21 +968,21 @@ void Record<ESM::MagicEffect>::print()
std::cout << " Icon: " << mData.mIcon << std::endl;
std::cout << " Flags: " << magicEffectFlags(mData.mData.mFlags) << std::endl;
std::cout << " Particle Texture: " << mData.mParticle << std::endl;
if (mData.mCasting != "")
if (!mData.mCasting.empty())
std::cout << " Casting Static: " << mData.mCasting << std::endl;
if (mData.mCastSound != "")
if (!mData.mCastSound.empty())
std::cout << " Casting Sound: " << mData.mCastSound << std::endl;
if (mData.mBolt != "")
if (!mData.mBolt.empty())
std::cout << " Bolt Static: " << mData.mBolt << std::endl;
if (mData.mBoltSound != "")
if (!mData.mBoltSound.empty())
std::cout << " Bolt Sound: " << mData.mBoltSound << std::endl;
if (mData.mHit != "")
if (!mData.mHit.empty())
std::cout << " Hit Static: " << mData.mHit << std::endl;
if (mData.mHitSound != "")
if (!mData.mHitSound.empty())
std::cout << " Hit Sound: " << mData.mHitSound << std::endl;
if (mData.mArea != "")
if (!mData.mArea.empty())
std::cout << " Area Static: " << mData.mArea << std::endl;
if (mData.mAreaSound != "")
if (!mData.mAreaSound.empty())
std::cout << " Area Sound: " << mData.mAreaSound << std::endl;
std::cout << " School: " << schoolLabel(mData.mData.mSchool)
<< " (" << mData.mData.mSchool << ")" << std::endl;
@ -1015,7 +1002,7 @@ void Record<ESM::Miscellaneous>::print()
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl;
@ -1032,9 +1019,9 @@ void Record<ESM::NPC>::print()
std::cout << " Head Model: " << mData.mHead << std::endl;
std::cout << " Race: " << mData.mRace << std::endl;
std::cout << " Class: " << mData.mClass << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
if (mData.mFaction != "")
if (!mData.mFaction.empty())
std::cout << " Faction: " << mData.mFaction << std::endl;
std::cout << " Flags: " << npcFlags(mData.mFlags) << std::endl;
@ -1083,14 +1070,12 @@ void Record<ESM::NPC>::print()
std::cout << " Gold: " << mData.mNpdt.mGold << std::endl;
}
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount
<< " Item: " << item.mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
for (const std::string &spell : mData.mSpells.mList)
std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport());
@ -1105,9 +1090,8 @@ void Record<ESM::NPC>::print()
std::cout << " AI U4:" << (int)mData.mAiData.mU4 << std::endl;
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
for (const ESM::AIPackage &package : mData.mAiPackage.mList)
printAIPackage(package);
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -1124,23 +1108,22 @@ void Record<ESM::Pathgrid>::print()
std::cout << " Edge Count: " << mData.mEdges.size() << std::endl;
int i = 0;
ESM::Pathgrid::PointList::iterator pit;
for (pit = mData.mPoints.begin(); pit != mData.mPoints.end(); ++pit)
for (const ESM::Pathgrid::Point &point : mData.mPoints)
{
std::cout << " Point[" << i << "]:" << std::endl;
std::cout << " Coordinates: (" << pit->mX << ","
<< pit->mY << "," << pit->mZ << ")" << std::endl;
std::cout << " Auto-Generated: " << (int)pit->mAutogenerated << std::endl;
std::cout << " Connections: " << (int)pit->mConnectionNum << std::endl;
std::cout << " Unknown: " << pit->mUnknown << std::endl;
std::cout << " Coordinates: (" << point.mX << ","
<< point.mY << "," << point.mZ << ")" << std::endl;
std::cout << " Auto-Generated: " << (int)point.mAutogenerated << std::endl;
std::cout << " Connections: " << (int)point.mConnectionNum << std::endl;
std::cout << " Unknown: " << point.mUnknown << std::endl;
i++;
}
i = 0;
ESM::Pathgrid::EdgeList::iterator eit;
for (eit = mData.mEdges.begin(); eit != mData.mEdges.end(); ++eit)
for (const ESM::Pathgrid::Edge &edge : mData.mEdges)
{
std::cout << " Edge[" << i << "]: " << eit->mV0 << " -> " << eit->mV1 << std::endl;
if (eit->mV0 >= mData.mData.mS2 || eit->mV1 >= mData.mData.mS2)
std::cout << " Edge[" << i << "]: " << edge.mV0 << " -> " << edge.mV1 << std::endl;
if (edge.mV0 >= mData.mData.mS2 || edge.mV1 >= mData.mData.mS2)
std::cout << " BAD POINT IN EDGE!" << std::endl;
i++;
}
@ -1183,9 +1166,8 @@ void Record<ESM::Race>::print()
<< " (" << mData.mData.mBonus[i].mSkill << ") = "
<< mData.mData.mBonus[i].mBonus << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
std::cout << " Power: " << *sit << std::endl;
for (const std::string &power : mData.mPowers.mList)
std::cout << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -1207,11 +1189,10 @@ void Record<ESM::Region>::print()
std::cout << " UnknownA: " << (int)mData.mData.mA << std::endl;
std::cout << " UnknownB: " << (int)mData.mData.mB << std::endl;
std::cout << " Map Color: " << mData.mMapColor << std::endl;
if (mData.mSleepList != "")
if (!mData.mSleepList.empty())
std::cout << " Sleep List: " << mData.mSleepList << std::endl;
std::vector<ESM::Region::SoundRef>::iterator sit;
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); ++sit)
std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl;
for (const ESM::Region::SoundRef &soundref : mData.mSoundList)
std::cout << " Sound: " << (int)soundref.mChance << " = " << soundref.mSound.toString() << std::endl;
}
template<>
@ -1225,15 +1206,12 @@ void Record<ESM::Script>::print()
std::cout << " Script Data Size: " << mData.mData.mScriptDataSize << std::endl;
std::cout << " Table Size: " << mData.mData.mStringTableSize << std::endl;
std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); ++vit)
std::cout << " Variable: " << *vit << std::endl;
for (const std::string &variable : mData.mVarNames)
std::cout << " Variable: " << variable << std::endl;
std::cout << " ByteCode: ";
std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); ++cit)
std::cout << boost::format("%02X") % (int)(*cit);
for (const unsigned char &byte : mData.mScriptData)
std::cout << boost::format("%02X") % (int)(byte);
std::cout << std::endl;
if (mPrintPlain)
@ -1268,7 +1246,8 @@ void Record<ESM::Skill>::print()
template<>
void Record<ESM::SoundGenerator>::print()
{
std::cout << " Creature: " << mData.mCreature << std::endl;
if (!mData.mCreature.empty())
std::cout << " Creature: " << mData.mCreature << std::endl;
std::cout << " Sound: " << mData.mSound << std::endl;
std::cout << " Type: " << soundTypeLabel(mData.mType)
<< " (" << mData.mType << ")" << std::endl;
@ -1316,15 +1295,15 @@ template<>
void Record<ESM::Weapon>::print()
{
// No names on VFX bolts
if (mData.mName != "")
if (!mData.mName.empty())
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl;
// No icons on VFX bolts or magic bolts
if (mData.mIcon != "")
if (!mData.mIcon.empty())
std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "")
if (!mData.mScript.empty())
std::cout << " Script: " << mData.mScript << std::endl;
if (mData.mEnchant != "")
if (!mData.mEnchant.empty())
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
std::cout << " Type: " << weaponTypeLabel(mData.mData.mType)
<< " (" << mData.mData.mType << ")" << std::endl;
@ -1356,25 +1335,25 @@ std::string Record<ESM::Cell>::getId() const
template<>
std::string Record<ESM::Land>::getId() const
{
return ""; // No ID for Land record
return std::string(); // No ID for Land record
}
template<>
std::string Record<ESM::MagicEffect>::getId() const
{
return ""; // No ID for MagicEffect record
return std::string(); // No ID for MagicEffect record
}
template<>
std::string Record<ESM::Pathgrid>::getId() const
{
return ""; // No ID for Pathgrid record
return std::string(); // No ID for Pathgrid record
}
template<>
std::string Record<ESM::Skill>::getId() const
{
return ""; // No ID for Skill record
return std::string(); // No ID for Skill record
}
} // end namespace

@ -6,7 +6,7 @@
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp>
#endif
#include <components/process/processinvoker.hpp>
@ -14,7 +14,7 @@
#include <components/config/launchersettings.hpp>
#include <components/settings/settings.hpp>
#endif
#include "ui_mainwindow.h"
class QListWidgetItem;

@ -470,6 +470,13 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
if (creature.mData.mSoul < 0)
messages.add(id, "Soul value is negative", "", CSMDoc::Message::Severity_Error);
if (creature.mAiData.mAlarm > 100)
messages.add(id, "Alarm rating is over 100", "", CSMDoc::Message::Severity_Warning);
if (creature.mAiData.mFight > 100)
messages.add(id, "Fight rating is over 100", "", CSMDoc::Message::Severity_Warning);
if (creature.mAiData.mFlee > 100)
messages.add(id, "Flee rating is over 100", "", CSMDoc::Message::Severity_Warning);
for (int i = 0; i < 6; ++i)
{
if (creature.mData.mAttack[i] < 0)
@ -700,6 +707,13 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
if (level <= 0)
messages.add(id, "Level is non-positive", "", CSMDoc::Message::Severity_Warning);
if (npc.mAiData.mAlarm > 100)
messages.add(id, "Alarm rating is over 100", "", CSMDoc::Message::Severity_Warning);
if (npc.mAiData.mFight > 100)
messages.add(id, "Fight rating is over 100", "", CSMDoc::Message::Severity_Warning);
if (npc.mAiData.mFlee > 100)
messages.add(id, "Flee rating is over 100", "", CSMDoc::Message::Severity_Warning);
if (gold < 0)
messages.add(id, "Gold count is negative", "", CSMDoc::Message::Severity_Error);
@ -1014,6 +1028,11 @@ template<typename Tool> void CSMTools::ReferenceableCheckStage::toolCheck (
template<typename List> void CSMTools::ReferenceableCheckStage::listCheck (
const List& someList, CSMDoc::Messages& messages, const std::string& someID)
{
if (someList.mChanceNone > 100)
{
messages.add(someID, "Chance that no object is used is over 100 percent", "", CSMDoc::Message::Severity_Warning);
}
for (unsigned i = 0; i < someList.mList.size(); ++i)
{
if (mReferencables.searchId(someList.mList[i].mId).first == -1)

@ -42,5 +42,11 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
if (chances != 100)
messages.add(id, "Weather chances do not add up to 100", "", CSMDoc::Message::Severity_Error);
for (const ESM::Region::SoundRef& sound : region.mSoundList)
{
if (sound.mChance > 100)
messages.add(id, "Chance of '" + sound.mSound.toString() + "' sound to play is over 100 percent", "", CSMDoc::Message::Severity_Warning);
}
/// \todo check data members that can't be edited in the table view
}

@ -205,7 +205,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer));
new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_UnsignedInteger8));
mBirthsigns.addColumn (new StringIdColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new RecordStateColumn<ESM::BirthSign>);
@ -326,11 +326,11 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
new NestedChildColumn (Columns::ColumnId_Interior, ColumnBase::Display_Boolean,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Ambient, ColumnBase::Display_Integer));
new NestedChildColumn (Columns::ColumnId_Ambient, ColumnBase::Display_Colour));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Sunlight, ColumnBase::Display_Integer));
new NestedChildColumn (Columns::ColumnId_Sunlight, ColumnBase::Display_Colour));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Fog, ColumnBase::Display_Integer));
new NestedChildColumn (Columns::ColumnId_Fog, ColumnBase::Display_Colour));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_FogDensity, ColumnBase::Display_Float));
mCells.getNestableColumn(index)->addColumn(
@ -989,23 +989,29 @@ void CSMWorld::Data::loadFallbackEntries()
std::make_pair("PrisonMarker", "marker_prison.nif")
};
for (const std::pair<std::string, std::string> marker : staticMarkers)
for (const std::pair<std::string, std::string> &marker : staticMarkers)
{
if (mReferenceables.searchId (marker.first)==-1)
{
ESM::Static newMarker;
newMarker.mId = marker.first;
newMarker.mModel = marker.second;
CSMWorld::Record<ESM::Static> record;
record.mBase = ESM::Static(marker.first, marker.second);
record.mBase = newMarker;
record.mState = CSMWorld::RecordBase::State_BaseOnly;
mReferenceables.appendRecord (record, CSMWorld::UniversalId::Type_Static);
}
}
for (const std::pair<std::string, std::string> marker : doorMarkers)
for (const std::pair<std::string, std::string> &marker : doorMarkers)
{
if (mReferenceables.searchId (marker.first)==-1)
{
ESM::Door newMarker;
newMarker.mId = marker.first;
newMarker.mModel = marker.second;
CSMWorld::Record<ESM::Door> record;
record.mBase = ESM::Door(marker.first, std::string(), marker.second, std::string(), std::string(), std::string());
record.mBase = newMarker;
record.mState = CSMWorld::RecordBase::State_BaseOnly;
mReferenceables.appendRecord (record, CSMWorld::UniversalId::Type_Door);
}

@ -128,13 +128,13 @@ CSMWorld::RefIdCollection::RefIdCollection()
ActorColumns actorsColumns (nameColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger8));
actorsColumns.mHello = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8));
actorsColumns.mFlee = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFight, ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFight, ColumnBase::Display_UnsignedInteger8));
actorsColumns.mFight = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiAlarm, ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiAlarm, ColumnBase::Display_UnsignedInteger8));
actorsColumns.mAlarm = &mColumns.back();
// Nested table
@ -645,7 +645,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemType, CSMWorld::ColumnBase::Display_Boolean));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemChanceNone, CSMWorld::ColumnBase::Display_Integer));
new RefIdColumn (Columns::ColumnId_LevelledItemChanceNone, CSMWorld::ColumnBase::Display_UnsignedInteger8));
mAdapters.insert (std::make_pair (UniversalId::Type_Activator,
new NameRefIdAdapter<ESM::Activator> (UniversalId::Type_Activator, nameColumns)));

@ -4,6 +4,8 @@
#include <QDialog>
#include <QModelIndex>
#ifndef Q_MOC_RUN
#include <boost/filesystem/path.hpp>
#include "adjusterwidget.hpp"
@ -12,6 +14,8 @@
Q_DECLARE_METATYPE (boost::filesystem::path)
#endif
#endif
#include "ui_filedialog.h"
namespace ContentSelectorView

@ -8,6 +8,7 @@
#include <QWidget>
#include <QEvent>
#ifndef Q_MOC_RUN
#include "../../model/world/data.hpp"
#include "../../model/world/land.hpp"
@ -15,6 +16,7 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp"
#endif
namespace CSVWidget
{

@ -3,7 +3,9 @@
#include <QWidget>
#ifndef Q_MOC_RUN
#include <boost/filesystem/path.hpp>
#endif
class QPushButton;
class QListWidget;

@ -14,9 +14,11 @@
#include <QHBoxLayout>
#include <QPushButton>
#ifndef Q_MOC_RUN
#include "scenetool.hpp"
#include "../../model/doc/document.hpp"
#endif
class QTableWidget;

@ -5,10 +5,12 @@
#include <QWidget>
#ifndef Q_MOC_RUN
#include "../../model/doc/document.hpp"
#include "../../model/world/scope.hpp"
#include "../../model/world/universalid.hpp"
#endif
namespace CSMDoc
{

@ -8,11 +8,13 @@
#include <QAbstractItemDelegate>
#include <QScrollArea>
#ifndef Q_MOC_RUN
#include "../doc/subview.hpp"
#include "../../model/world/columnbase.hpp"
#include "../../model/world/commanddispatcher.hpp"
#include "../../model/world/universalid.hpp"
#endif
class QDataWidgetMapper;
class QSize;

@ -6,8 +6,11 @@
#include <QAbstractTableModel>
#include <QStyledItemDelegate>
#ifndef Q_MOC_RUN
#include "../../model/world/columnbase.hpp"
#include "../../model/doc/document.hpp"
#endif
class QUndoStack;

@ -20,14 +20,14 @@ void releaseArgv();
int Java_org_libsdl_app_SDLActivity_getMouseX(JNIEnv *env, jclass cls, jobject obj) {
int ret = 0;
SDL_GetMouseState(&ret, nullptr);
SDL_GetMouseState(&ret, NULL);
return ret;
}
int Java_org_libsdl_app_SDLActivity_getMouseY(JNIEnv *env, jclass cls, jobject obj) {
int ret = 0;
SDL_GetMouseState(nullptr, &ret);
SDL_GetMouseState(NULL, &ret);
return ret;
}
@ -35,6 +35,17 @@ int Java_org_libsdl_app_SDLActivity_isMouseShown(JNIEnv *env, jclass cls, jobjec
return SDL_ShowCursor(SDL_QUERY);
}
extern SDL_Window *Android_Window;
int SDL_SendMouseMotion(SDL_Window * window, int mouseID, int relative, int x, int y);
void Java_org_libsdl_app_SDLActivity_sendRelativeMouseMotion(JNIEnv *env, jclass cls, int x, int y) {
SDL_SendMouseMotion(Android_Window, 0, 1, x, y);
}
int SDL_SendMouseButton(SDL_Window * window, int mouseID, Uint8 state, Uint8 button);
void Java_org_libsdl_app_SDLActivity_sendMouseButton(JNIEnv *env, jclass cls, int state, int button) {
SDL_SendMouseButton(Android_Window, 0, state, button);
}
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) {
setenv("OPENMW_DECOMPRESS_TEXTURES", "1", 1);

@ -247,6 +247,9 @@ namespace MWBase
virtual float getActorsProcessingRange() const = 0;
virtual bool onOpen(const MWWorld::Ptr& ptr) = 0;
virtual void onClose(const MWWorld::Ptr& ptr) = 0;
/// Check if the target actor was detected by an observer
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) = 0;

@ -451,6 +451,8 @@ namespace MWBase
End of tes3mp addition
*/
virtual void updateAnimatedCollisionShape(const MWWorld::Ptr &ptr) = 0;
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0;
///< cast a Ray and return true if there is an object in the ray path.

@ -285,6 +285,8 @@ namespace MWGui
if (mModel)
mModel->onClose();
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr);
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)

@ -133,22 +133,23 @@ namespace MWGui
public:
CopyFramebufferToTextureCallback(osg::Texture2D* texture)
: mTexture(texture)
, oneshot(true)
{
}
virtual void operator () (osg::RenderInfo& renderInfo) const
{
if (!oneshot)
return;
oneshot = false;
int w = renderInfo.getCurrentCamera()->getViewport()->width();
int h = renderInfo.getCurrentCamera()->getViewport()->height();
mTexture->copyTexImage2D(*renderInfo.getState(), 0, 0, w, h);
// Callback removes itself when done
if (renderInfo.getCurrentCamera())
renderInfo.getCurrentCamera()->setInitialDrawCallback(nullptr);
}
private:
osg::ref_ptr<osg::Texture2D> mTexture;
mutable bool oneshot;
};
class DontComputeBoundCallback : public osg::Node::ComputeBoundingSphereCallback
@ -308,6 +309,8 @@ namespace MWGui
mGuiTexture.reset(new osgMyGUI::OSGTexture(mTexture));
}
// Notice that the next time this is called, the current CopyFramebufferToTextureCallback will be deleted
// so there's no memory leak as at most one object of type CopyFramebufferToTextureCallback is allocated at a time.
mViewer->getCamera()->setInitialDrawCallback(new CopyFramebufferToTextureCallback(mTexture));
mBackgroundImage->setBackgroundImage("");

@ -64,6 +64,7 @@ namespace MWInput
, mUserFile(userFile)
, mDragDrop(false)
, mGrabCursor (Settings::Manager::getBool("grab cursor", "Input"))
, mInvertX (Settings::Manager::getBool("invert x axis", "Input"))
, mInvertY (Settings::Manager::getBool("invert y axis", "Input"))
, mControlsDisabled(false)
, mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input"))
@ -479,7 +480,7 @@ namespace MWInput
float rot[3];
rot[0] = yAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier;
rot[1] = 0.0f;
rot[2] = xAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f);
rot[2] = xAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f) * (mInvertX ? -1 : 1);
// Only actually turn player when we're not in vanity mode
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
@ -658,6 +659,9 @@ namespace MWInput
for (Settings::CategorySettingVector::const_iterator it = changed.begin();
it != changed.end(); ++it)
{
if (it->first == "Input" && it->second == "invert x axis")
mInvertX = Settings::Manager::getBool("invert x axis", "Input");
if (it->first == "Input" && it->second == "invert y axis")
mInvertY = Settings::Manager::getBool("invert y axis", "Input");
@ -840,7 +844,7 @@ namespace MWInput
{
resetIdleTime();
float x = arg.xrel * mCameraSensitivity * (1.0f/256.f);
float x = arg.xrel * mCameraSensitivity * (1.0f/256.f) * (mInvertX ? -1 : 1);
float y = arg.yrel * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier;
float rot[3];
@ -1239,7 +1243,7 @@ namespace MWInput
void InputManager::toggleWalking()
{
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
if (MWBase::Environment::get().getWindowManager()->isGuiMode() || SDL_IsTextInputActive()) return;
mAlwaysRunActive = !mAlwaysRunActive;
Settings::Manager::setBool("always run", "Input", mAlwaysRunActive);

@ -175,6 +175,7 @@ namespace MWInput
bool mGrabCursor;
bool mInvertX;
bool mInvertY;
bool mControlsDisabled;

@ -413,5 +413,5 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld::
bool MWMechanics::AiPackage::canActorMoveByZAxis(const MWWorld::Ptr& actor) const
{
MWBase::World* world = MWBase::Environment::get().getWorld();
return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor);
return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor) || !world->isActorCollisionEnabled(actor);
}

@ -209,7 +209,8 @@ namespace MWMechanics
}
bool actorCanMoveByZ = (actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor))
|| MWBase::Environment::get().getWorld()->isFlying(actor);
|| MWBase::Environment::get().getWorld()->isFlying(actor)
|| !MWBase::Environment::get().getWorld()->isActorCollisionEnabled(actor);
if(actorCanMoveByZ && mDistance > 0) {
// Typically want to idle for a short time before the next wander

@ -435,6 +435,43 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
}
}
bool CharacterController::onOpen()
{
if (mPtr.getTypeName() == typeid(ESM::Container).name())
{
if (!mAnimation->hasAnimation("containeropen"))
return true;
if (mAnimation->isPlaying("containeropen"))
return false;
if (mAnimation->isPlaying("containerclose"))
return false;
mAnimation->play("containeropen", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, "start", "stop", 0.f, 0);
if (mAnimation->isPlaying("containeropen"))
return false;
}
return true;
}
void CharacterController::onClose()
{
if (mPtr.getTypeName() == typeid(ESM::Container).name())
{
if (!mAnimation->hasAnimation("containerclose"))
return;
float complete, startPoint = 0.f;
bool animPlaying = mAnimation->getInfo("containeropen", &complete);
if (animPlaying)
startPoint = 1.f - complete;
mAnimation->play("containerclose", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, "start", "stop", startPoint, 0);
}
}
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force)
{
if (movement == mMovementState && idle == mIdleState && !force)
@ -1109,6 +1146,8 @@ void CharacterController::handleTextKey(const std::string &groupname, const std:
else if (groupname == "shield" && evt.compare(off, len, "block hit") == 0)
mPtr.getClass().block(mPtr);
else if (groupname == "containeropen" && evt.compare(off, len, "loot") == 0)
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, mPtr);
}
void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
@ -1711,11 +1750,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
}
}
// We should reset player's idle animation in the first-person mode.
if (resetIdle && mPtr == player && MWBase::Environment::get().getWorld()->isFirstPerson())
idle = CharState_None;
// In other cases we should not break swim and sneak animations
// We should not break swim and sneak animations
if (resetIdle &&
idle != CharState_IdleSneak && idle != CharState_IdleSwim &&
mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
@ -1975,6 +2010,7 @@ void CharacterController::update(float duration, bool animationOnly)
bool incapacitated = (cls.getCreatureStats(mPtr).isParalyzed() || cls.getCreatureStats(mPtr).getKnockedDown());
bool inwater = world->isSwimming(mPtr);
bool flying = world->isFlying(mPtr);
bool solid = world->isActorCollisionEnabled(mPtr);
// Can't run and sneak while flying (see speed formula in Npc/Creature::getSpeed)
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !flying;
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !flying;
@ -1983,7 +2019,7 @@ void CharacterController::update(float duration, bool animationOnly)
//Force Jump Logic
bool isMoving = (std::abs(cls.getMovementSettings(mPtr).mPosition[0]) > .5 || std::abs(cls.getMovementSettings(mPtr).mPosition[1]) > .5);
if(!inwater && !flying)
if(!inwater && !flying && solid)
{
//Force Jump
if(stats.getMovementFlag(MWMechanics::CreatureStats::Flag_ForceJump))
@ -2124,12 +2160,12 @@ void CharacterController::update(float duration, bool animationOnly)
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
if(sneak || inwater || flying || incapacitated)
if(sneak || inwater || flying || incapacitated || !solid)
vec.z() = 0.0f;
bool inJump = true;
bool playLandingSound = false;
if(!onground && !flying && !inwater)
if(!onground && !flying && !inwater && solid)
{
// In the air (either getting up —ascending part of jump— or falling).
@ -2182,7 +2218,7 @@ void CharacterController::update(float duration, bool animationOnly)
}
}
}
else if(mJumpState == JumpState_InAir && !inwater && !flying)
else if(mJumpState == JumpState_InAir && !inwater && !flying && solid)
{
forcestateupdate = true;
jumpstate = JumpState_Landing;
@ -2221,7 +2257,7 @@ void CharacterController::update(float duration, bool animationOnly)
}
else
{
if(mPtr.getClass().isNpc() && mJumpState == JumpState_InAir && !flying)
if(mPtr.getClass().isNpc() && mJumpState == JumpState_InAir && !flying && solid)
playLandingSound = true;
jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None;

@ -259,6 +259,9 @@ public:
void update(float duration, bool animationOnly=false);
bool onOpen();
void onClose();
void persistAnimationState();
void unpersistAnimationState();

@ -871,6 +871,20 @@ namespace MWMechanics
return false;
}
bool MechanicsManager::onOpen(const MWWorld::Ptr& ptr)
{
if(ptr.getClass().isActor())
return true;
else
return mObjects.onOpen(ptr);
}
void MechanicsManager::onClose(const MWWorld::Ptr& ptr)
{
if(!ptr.getClass().isActor())
mObjects.onClose(ptr);
}
void MechanicsManager::persistAnimationStates()
{
mActors.persistAnimationStates();

@ -192,6 +192,9 @@ namespace MWMechanics
virtual void playerLoaded() override;
virtual bool onOpen(const MWWorld::Ptr& ptr) override;
virtual void onClose(const MWWorld::Ptr& ptr) override;
virtual int countSavedGameRecords() const override;
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override;

@ -1,8 +1,10 @@
#include "objects.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm/loadcont.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "movement.hpp"
@ -77,6 +79,40 @@ void Objects::update(float duration, bool paused)
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
iter->second->update(duration);
}
else
{
// We still should play container opening animation in the Container GUI mode.
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
if(mode != MWGui::GM_Container)
return;
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
{
if (iter->first.getTypeName() != typeid(ESM::Container).name())
continue;
if (iter->second->isAnimPlaying("containeropen"))
{
iter->second->update(duration);
MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(iter->first);
}
}
}
}
bool Objects::onOpen(const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mObjects.find(ptr);
if(iter != mObjects.end())
return iter->second->onOpen();
return false;
}
void Objects::onClose(const MWWorld::Ptr& ptr)
{
PtrControllerMap::iterator iter = mObjects.find(ptr);
if(iter != mObjects.end())
iter->second->onClose();
}
bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist)

@ -38,6 +38,9 @@ namespace MWMechanics
void update(float duration, bool paused);
///< Update object animations
bool onOpen(const MWWorld::Ptr& ptr);
void onClose(const MWWorld::Ptr& ptr);
bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false);
void skipAnimation(const MWWorld::Ptr& ptr);
void persistAnimationStates();

@ -1361,7 +1361,7 @@ namespace MWPhysics
float heightDiff = position.z() - oldHeight;
MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first);
if ((wasOnGround && physicActor->getOnGround()) || flying || world->isSwimming(iter->first) || slowFall < 1)
if ((numSteps > 0 && wasOnGround && physicActor->getOnGround()) || flying || world->isSwimming(iter->first) || slowFall < 1)
stats.land(iter->first == player);
else if (heightDiff < 0)
stats.addToFallHeight(-heightDiff);
@ -1385,6 +1385,13 @@ namespace MWPhysics
#endif
}
void PhysicsSystem::updateAnimatedCollisionShape(const MWWorld::Ptr& object)
{
ObjectMap::iterator found = mObjects.find(object);
if (found != mObjects.end())
found->second->animateCollisionShapes(mCollisionWorld);
}
void PhysicsSystem::debugDraw()
{
if (mDebugDrawer.get())

@ -188,6 +188,8 @@ namespace MWPhysics
End of tes3mp addition
*/
void updateAnimatedCollisionShape(const MWWorld::Ptr& object);
template <class Function>
void forEachAnimatedObject(Function&& function) const
{

@ -4,6 +4,7 @@
#include <vector>
#include <memory>
#include <array>
#include <atomic>
#include <stdint.h>
@ -279,7 +280,7 @@ private:
std::unique_ptr<Sound_Loudness> mLoudnessAnalyzer;
volatile bool mIsFinished;
std::atomic<bool> mIsFinished;
void updateAll(bool local);
@ -313,7 +314,7 @@ struct OpenAL_Output::StreamThread : public OpenThreads::Thread {
typedef std::vector<OpenAL_SoundStream*> StreamVec;
StreamVec mStreams;
volatile bool mQuitNow;
std::atomic<bool> mQuitNow;
OpenThreads::Mutex mMutex;
OpenThreads::Condition mCondVar;

@ -1,6 +1,7 @@
#include "actionopen.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwmechanics/disease.hpp"
@ -20,6 +21,9 @@ namespace MWWorld
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return;
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
return;
MWMechanics::diseaseContact(actor, getTarget());
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container, getTarget());

@ -1,5 +1,7 @@
#include "cellpreloader.hpp"
#include <atomic>
#include <components/debug/debuglog.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/resource/resourcesystem.hpp>
@ -159,7 +161,7 @@ namespace MWWorld
MWRender::LandManager* mLandManager;
bool mPreloadInstances;
volatile bool mAbort;
std::atomic<bool> mAbort;
osg::ref_ptr<Terrain::View> mTerrainView;
@ -392,7 +394,7 @@ namespace MWWorld
}
private:
volatile bool mAbort;
std::atomic<bool> mAbort;
std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews;
Terrain::World* mWorld;
std::vector<osg::Vec3f> mPreloadPositions;

@ -163,7 +163,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
}
if (mListener)
mListener->itemAdded(itemPtr, count);
mListener->itemAdded(*retVal, count);
return retVal;
}

@ -1007,14 +1007,13 @@ namespace MWWorld
}
void Store<ESM::Attribute>::setUp()
{
for (int i = 0; i < ESM::Attribute::Length; ++i) {
mStatic.push_back(
ESM::Attribute(
ESM::Attribute::sAttributeIds[i],
ESM::Attribute::sGmstAttributeIds[i],
ESM::Attribute::sGmstAttributeDescIds[i]
)
);
for (int i = 0; i < ESM::Attribute::Length; ++i)
{
ESM::Attribute newAttribute;
newAttribute.mId = ESM::Attribute::sAttributeIds[i];
newAttribute.mName = ESM::Attribute::sGmstAttributeIds[i];
newAttribute.mDescription = ESM::Attribute::sGmstAttributeDescIds[i];
mStatic.push_back(newAttribute);
}
}
size_t Store<ESM::Attribute>::getSize() const
@ -1059,18 +1058,20 @@ namespace MWWorld
{
// Load default marker definitions, if game files do not have them for some reason
std::pair<std::string, std::string> markers[] = {
std::make_pair("DivineMarker", "marker_divine.nif"),
std::make_pair("DoorMarker", "marker_arrow.nif"),
std::make_pair("NorthMarker", "marker_north.nif"),
std::make_pair("TempleMarker", "marker_temple.nif"),
std::make_pair("TravelMarker", "marker_travel.nif")
std::make_pair("divinemarker", "marker_divine.nif"),
std::make_pair("doormarker", "marker_arrow.nif"),
std::make_pair("northmarker", "marker_north.nif"),
std::make_pair("templemarker", "marker_temple.nif"),
std::make_pair("travelmarker", "marker_travel.nif")
};
for (const std::pair<std::string, std::string> marker : markers)
for (const std::pair<std::string, std::string> &marker : markers)
{
if (search(marker.first) == 0)
{
ESM::Static newMarker = ESM::Static(marker.first, marker.second);
ESM::Static newMarker;
newMarker.mId = marker.first;
newMarker.mModel = marker.second;
std::pair<typename Static::iterator, bool> ret = mStatic.insert(std::make_pair(marker.first, newMarker));
if (ret.first != mStatic.end())
{
@ -1085,14 +1086,16 @@ namespace MWWorld
{
// Load default Door type marker definitions
std::pair<std::string, std::string> markers[] = {
std::make_pair("PrisonMarker", "marker_prison.nif")
std::make_pair("prisonmarker", "marker_prison.nif")
};
for (const std::pair<std::string, std::string> marker : markers)
for (const std::pair<std::string, std::string> &marker : markers)
{
if (search(marker.first) == 0)
{
ESM::Door newMarker = ESM::Door(marker.first, std::string(), marker.second, std::string(), std::string(), std::string());
ESM::Door newMarker;
newMarker.mId = marker.first;
newMarker.mModel = marker.second;
std::pair<typename Static::iterator, bool> ret = mStatic.insert(std::make_pair(marker.first, newMarker));
if (ret.first != mStatic.end())
{

@ -1587,7 +1587,7 @@ namespace MWWorld
pos.z() += 20; // place slightly above. will snap down to ground with code below
if (force || !isFlying(ptr))
if (force || !ptr.getClass().isActor() || (!isFlying(ptr) && isActorCollisionEnabled(ptr)))
{
osg::Vec3f traced = mPhysics->traceDown(ptr, pos, Constants::CellSizeInUnits);
if (traced.z() < pos.z())
@ -1757,6 +1757,11 @@ namespace MWWorld
End of tes3mp addition
*/
void World::updateAnimatedCollisionShape(const Ptr &ptr)
{
mPhysics->updateAnimatedCollisionShape(ptr);
}
void World::doPhysics(float duration)
{
mPhysics->stepSimulation(duration);
@ -2521,11 +2526,11 @@ namespace MWWorld
bool World::isFlying(const MWWorld::Ptr &ptr) const
{
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
if(!ptr.getClass().isActor())
return false;
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
if (stats.isDead())
return false;
@ -2537,7 +2542,7 @@ namespace MWWorld
return true;
const MWPhysics::Actor* actor = mPhysics->getActor(ptr);
if(!actor || !actor->getCollisionMode())
if(!actor)
return true;
return false;

@ -547,6 +547,8 @@ namespace MWWorld
End of tes3mp addition
*/
void updateAnimatedCollisionShape(const Ptr &ptr) override;
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override;
///< cast a Ray and return true if there is an object in the ray path.

@ -9,9 +9,10 @@
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp>
#endif
#include <components/config/gamesettings.hpp>
#include <components/config/launchersettings.hpp>
#endif
namespace Wizard
{

@ -1,5 +1,6 @@
# This module accepts the following env variable
# OSGPlugins_LIB_DIR - <OpenSceneGraph>/lib/osgPlugins-<X.X.X> , path to search plugins
# OSGPlugins_DONT_FIND_DEPENDENCIES - Set to skip also finding png, zlib and jpeg
#
# Once done this will define
# OSGPlugins_FOUND - System has the all required components.
@ -41,10 +42,12 @@ foreach(_library ${OSGPlugins_FIND_COMPONENTS})
list(APPEND OSGPlugins_PROCESS_LIBS ${_component}_LIBRARY)
endforeach()
foreach(_dependency PNG ZLIB JPEG) # needed by osgdb_png or osgdb_jpeg
libfind_package(OSGPlugins ${_dependency})
set(${_dependency}_LIBRARY_OPTS ${_dependency}_LIBRARY)
#list(APPEND OSGPlugins_PROCESS_LIBS ${_dependency}_LIBRARY)
endforeach()
if(NOT DEFINED OSGPlugins_DONT_FIND_DEPENDENCIES)
foreach(_dependency PNG ZLIB JPEG) # needed by osgdb_png or osgdb_jpeg
libfind_package(OSGPlugins ${_dependency})
set(${_dependency}_LIBRARY_OPTS ${_dependency}_LIBRARY)
#list(APPEND OSGPlugins_PROCESS_LIBS ${_dependency}_LIBRARY)
endforeach()
endif()
libfind_process(OSGPlugins)

@ -2,8 +2,42 @@
#include <components/crashcatcher/crashcatcher.hpp>
#ifdef _WIN32
# undef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
namespace Debug
{
#ifdef _WIN32
bool attachParentConsole()
{
if (GetConsoleWindow() != nullptr)
return true;
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
fflush(stdout);
fflush(stderr);
std::cout.flush();
std::cerr.flush();
// this looks dubious but is really the right way
_wfreopen(L"CON", L"w", stdout);
_wfreopen(L"CON", L"w", stderr);
_wfreopen(L"CON", L"r", stdin);
freopen("CON", "w", stdout);
freopen("CON", "w", stderr);
freopen("CON", "r", stdin);
return true;
}
return false;
}
#endif
std::streamsize DebugOutputBase::write(const char *str, std::streamsize size)
{
// Skip debug level marker
@ -52,6 +86,10 @@ namespace Debug
int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], const std::string& appName)
{
#if defined _WIN32
(void)Debug::attachParentConsole();
#endif
// Some objects used to redirect cout and cerr
// Scope must be here, so this still works inside the catch block for logging exceptions
std::streambuf* cout_rdbuf = std::cout.rdbuf ();

@ -10,6 +10,12 @@
#include "debuglog.hpp"
#if defined _WIN32 && defined _DEBUG
# undef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
namespace Debug
{
// ANSI colors for terminal
@ -43,11 +49,11 @@ namespace Debug
}
};
#if defined(_WIN32) && defined(_DEBUG)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif // !WIN32_LEAN_AND_MEAN
#include <Windows.h>
#ifdef _WIN32
bool attachParentConsole();
#endif
#if defined _WIN32 && defined _DEBUG
class DebugOutput : public DebugOutputBase
{
public:

@ -56,12 +56,12 @@ namespace DetourNavigator
Value(Value&& other)
: mOwner(other.mOwner), mIterator(other.mIterator)
{
other.mIterator = ItemIterator();
other.mOwner = nullptr;
}
~Value()
{
if (mIterator != ItemIterator())
if (mOwner)
mOwner->releaseItem(mIterator);
}
@ -69,16 +69,13 @@ namespace DetourNavigator
Value& operator =(Value&& other)
{
if (mIterator == other.mIterator)
return *this;
if (mIterator != ItemIterator())
if (mOwner)
mOwner->releaseItem(mIterator);
mOwner = other.mOwner;
mIterator = other.mIterator;
other.mIterator = ItemIterator();
other.mOwner = nullptr;
return *this;
}
@ -90,7 +87,7 @@ namespace DetourNavigator
operator bool() const
{
return mIterator != ItemIterator();
return mOwner;
}
private:

@ -32,13 +32,6 @@ struct Attribute
static const std::string sGmstAttributeIds[Length];
static const std::string sGmstAttributeDescIds[Length];
static const std::string sAttributeIcons[Length];
Attribute(AttributeID id, const std::string &name, const std::string &description)
: mId(id)
, mName(name)
, mDescription(description)
{
}
};
}
#endif

@ -22,21 +22,6 @@ struct Door
void blank();
///< Set record to default state (does not touch the ID).
Door(const std::string id, const std::string name, const std::string &model,
const std::string script, const std::string opensound, const std::string closesound)
: mId(id)
, mName(name)
, mModel(model)
, mScript(script)
, mOpenSound(opensound)
, mCloseSound(closesound)
{
}
Door()
{
}
};
}
#endif

@ -33,16 +33,6 @@ struct Static
void blank();
///< Set record to default state (does not touch the ID).
Static(const std::string id, const std::string &model)
: mId(id)
, mModel(model)
{
}
Static()
{
}
};
}
#endif

@ -1,70 +1,95 @@
#include "fallback.hpp"
#include <boost/lexical_cast.hpp>
#include <components/debug/debuglog.hpp>
#include <boost/lexical_cast.hpp>
namespace Fallback
{
bool stob(std::string const& s) {
return s != "0";
}
Map::Map(const std::map<std::string,std::string>& fallback):mFallbackMap(fallback)
{}
std::string Map::getFallbackString(const std::string& fall) const
{
std::map<std::string,std::string>::const_iterator it;
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
if ((it = mFallbackMap.find(fall)) == mFallbackMap.end())
{
return "";
return std::string();
}
return it->second;
}
float Map::getFallbackFloat(const std::string& fall) const
{
std::string fallback=getFallbackString(fall);
if (fallback.empty())
return 0;
else
return boost::lexical_cast<float>(fallback);
std::string fallback = getFallbackString(fall);
if (!fallback.empty())
{
try
{
// We have to rely on Boost because std::stof from C++11
// uses the current locale for separators which we don't want and often silently ignores parsing errors.
return boost::lexical_cast<float>(fallback);
}
catch (boost::bad_lexical_cast&)
{
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << fallback << ") is not a valid number, using 0 as a fallback";
}
}
return 0;
}
int Map::getFallbackInt(const std::string& fall) const
{
std::string fallback=getFallbackString(fall);
if (fallback.empty())
return 0;
else
return std::stoi(fallback);
std::string fallback = getFallbackString(fall);
if (!fallback.empty())
{
try
{
return std::stoi(fallback);
}
catch (const std::invalid_argument&)
{
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << fallback << ") is not a valid number, using 0 as a fallback";
}
catch (const std::out_of_range&)
{
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << fallback << ") is out of range, using 0 as a fallback";
}
}
return 0;
}
bool Map::getFallbackBool(const std::string& fall) const
{
std::string fallback=getFallbackString(fall);
if (fallback.empty())
return false;
else
return stob(fallback);
std::string fallback = getFallbackString(fall);
return !fallback.empty() && fallback != "0";
}
osg::Vec4f Map::getFallbackColour(const std::string& fall) const
{
std::string sum=getFallbackString(fall);
if (sum.empty())
return osg::Vec4f(0.5f,0.5f,0.5f,1.f);
else
std::string sum = getFallbackString(fall);
if (!sum.empty())
{
std::string ret[3];
unsigned int j=0;
for(unsigned int i=0;i<sum.length();++i){
if(sum[i]==',') j++;
else if (sum[i] != ' ') ret[j]+=sum[i];
try
{
std::string ret[3];
unsigned int j = 0;
for (unsigned int i = 0; i < sum.length(); ++i)
{
if(sum[i]==',') j++;
else if (sum[i] != ' ') ret[j]+=sum[i];
}
return osg::Vec4f(std::stoi(ret[0])/255.f,std::stoi(ret[1])/255.f,std::stoi(ret[2])/255.f, 1.f);
}
catch (const std::invalid_argument&)
{
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << sum << ") is not a valid color, using middle gray as a fallback";
}
return osg::Vec4f(std::stoi(ret[0])/255.f,std::stoi(ret[1])/255.f,std::stoi(ret[2])/255.f, 1.f);
}
return osg::Vec4f(0.5f,0.5f,0.5f,1.f);
}
}

@ -2,6 +2,8 @@
#include <cassert>
#include <osg/Version>
namespace SceneUtil
{
@ -176,6 +178,10 @@ void MorphGeometry::cull(osg::NodeVisitor *nv)
positionDst->dirty();
#if OSG_MIN_VERSION_REQUIRED(3, 5, 6)
geom.dirtyGLObjects();
#endif
nv->pushOntoNodePath(&geom);
nv->apply(geom);
nv->popFromNodePath();

@ -3,6 +3,8 @@
#include <stdexcept>
#include <cstdlib>
#include <osg/Version>
#include <components/debug/debuglog.hpp>
#include "skeleton.hpp"
@ -235,6 +237,10 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
if (tangentDst)
tangentDst->dirty();
#if OSG_MIN_VERSION_REQUIRED(3, 5, 6)
geom.dirtyGLObjects();
#endif
nv->pushOntoNodePath(&geom);
nv->apply(geom);
nv->popFromNodePath();

@ -9,6 +9,7 @@
#include <osg/Referenced>
#include <osg/ref_ptr>
#include <atomic>
#include <queue>
namespace SceneUtil
@ -87,7 +88,7 @@ namespace SceneUtil
private:
WorkQueue* mWorkQueue;
volatile bool mActive;
std::atomic<bool> mActive;
};

@ -4,9 +4,8 @@ Fonts
Morrowind .fnt fonts
--------------------
Morrowind uses a custom ``.fnt`` file format. It is not compatible with the Windows Font File ``.fnt`` format,
nor compatible with ``.fnt`` formats from any other Bethesda games. To our knowledge,
the format is undocumented and no tools for viewing or editing these fonts exist.
Morrowind uses a custom ``.fnt`` file format. It is not compatible with the Windows Font File ``.fnt`` format.
To our knowledge, the format is undocumented.
OpenMW can load this format and convert it on the fly into something usable
(see font loader `source code <https://github.com/OpenMW/openmw/blob/master/components/fontloader/fontloader.cpp#L210>`_).
@ -16,20 +15,62 @@ In OpenMW 0.32, an --export-fonts command line option was added to write the con
TrueType fonts
--------------
Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts.
This is the recommended way to create new fonts.
Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts.
0.45.0+ way
-----------
This is the recommended way to install replacement fonts.
- To replace the primary "Magic Cards" font:
#. Download `Pelagiad <https://isaskar.github.io/Pelagiad/>`_ by Isak Larborn (aka Isaskar).
#. Create ``Fonts`` folder at the location of your ``openmw.cfg``.
#. Copy ``openmw_font.xml`` and ``Pelagiad.ttf`` files into the folder.
#. If desired, you can now delete the original ``Magic_Cards.*`` files from your ``Data Files/Fonts`` directory.
#. Pelagiad glyphs may appear to be pretty small, so open ``openmw.cfg`` and adjust the following settings as you deem necessary::
[GUI]
font size = 17
ttf resolution = 96
- You can also replace the Daedric font:
#. Download `Ayembedt <https://github.com/georgd/OpenMW-Fonts>`_ by Georg Duffner.
#. Install ``OMWAyembedt.otf`` into the ``Fonts`` folder.
#. Add the following lines into ``openmw_font.xml``::
<Resource type="ResourceTrueTypeFont" name="Daedric">
<Property key="Source" value="OMWAyembedt.otf"/>
<Property key="Antialias" value="false"/>
<Property key="TabWidth" value="8"/>
<Property key="OffsetHeight" value="0"/>
<Codes>
<Code range="32"/>
<Code range="65 90"/>
<Code range="97 122"/>
</Codes>
</Resource>
#. This font is missing a few glyphs (mostly punctuation), but it has all the primary glyphs. If desired, you can now delete the original ``daedric.*`` files from your ``Data Files/Fonts`` directory.
Any Resolution or Size properties in the file have no effect because the engine settings override them.
The engine automatically takes UI scaling factor into account, so don't account for it when tweaking the settings.
Pre-0.45.0 way
--------------
- To replace the primary "Magic Cards" font:
#. Download `Pelagiad <https://isaskar.github.io/Pelagiad/>`_ by Isak Larborn (aka Isaskar).
#. Install the ``openmw_font.xml`` file into ``resources/mygui/openmw_font.xml`` in your OpenMW installation.
#. Copy ``Pelagiad.ttf`` into ``resources/mygui/`` as well.
#. If desired, you can now delete the original ``Magic_Cards.*`` files from your Data Files/Fonts directory.
#. If desired, you can now delete the original ``Magic_Cards.*`` files from your ``Data Files/Fonts`` directory.
- You can also replace the Daedric font:
#. Download `Ayembedt <https://github.com/georgd/OpenMW-Fonts>`_ by Georg Duffner.
#. Install ``OMWAyembedt.otf`` into ``/resources/mygui/`` folder in your OpenMW installation.
#. Add the following lines to openmw_font.xml::
#. Add the following lines to ``openmw_font.xml``::
<Resource type="ResourceTrueTypeFont" name="Daedric">
<Property key="Source" value="OMWAyembedt.otf"/>
@ -45,12 +86,12 @@ This is the recommended way to create new fonts.
</Codes>
</Resource>
#. This font is missing a few glyphs (mostly punctuation), but is complete in the primary glyphs. If desired, you can now delete the original ``daedric.*`` files from your Data Files/Fonts directory.
#. This font is missing a few glyphs (mostly punctuation), but it has all the primary glyphs. If desired, you can now delete the original ``daedric.*`` files from your ``Data Files/Fonts`` directory.
- Another replacement for the Daedric font is `Oblivion <http://www.uesp.net/wiki/File:Obliviontt.zip>`_ by Dongle.
#. Install the ``Oblivion.ttf`` file resources/mygui/.
#. The openmw_fonts.xml entry is::
#. Install the ``Oblivion.ttf`` file into ``resources/mygui/``.
#. The ``openmw_font.xml`` entry is::
<Resource type="ResourceTrueTypeFont" name="Daedric">
<Property key="Source" value="Oblivion.ttf"/>
@ -80,7 +121,7 @@ This is the recommended way to create new fonts.
Bitmap fonts
------------
Morrowind ``.fnt`` files are essentially a bitmap font, but using them is discouraged because of no Unicode support.
Morrowind ``.fnt`` files are essentially a bitmap font, but using them is discouraged because they don't have Unicode support.
MyGUI has its own format for bitmap fonts. An example can be seen by using the --export-fonts command line option (see above),
which converts Morrowind ``.fnt`` to a MyGUI bitmap font.
This is the recommended format to use if you wish to edit Morrowind's bitmap font or create a new bitmap font.

@ -94,6 +94,20 @@ meaning that it should remain set at 1.0 unless the player desires to have diffe
This setting can only be configured by editing the settings configuration file.
invert x axis
-------------
:Type: boolean
:Range: True/False
:Default: False
Invert the horizontal axis while not in GUI mode.
If this setting is true, moving the mouse to the left will cause the view to rotate counter-clockwise,
while moving it to the right will cause the view to rotate clockwise. This setting does not affect cursor movement in GUI mode.
This setting can be toggled in game with the Invert X Axis button in the Controls panel of the Options menu.
invert y axis
-------------

@ -2,8 +2,10 @@
#define VIDEOPLAYER_VIDEOSTATE_H
#include <stdint.h>
#include <atomic>
#include <vector>
#include <memory>
#include <string>
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
@ -77,7 +79,7 @@ struct PacketQueue {
{ clear(); }
AVPacketList *first_pkt, *last_pkt;
volatile bool flushing;
std::atomic<bool> flushing;
int nb_packets;
int size;
@ -168,12 +170,12 @@ struct VideoState {
std::unique_ptr<ParseThread> parse_thread;
std::unique_ptr<VideoThread> video_thread;
volatile bool mSeekRequested;
std::atomic<bool> mSeekRequested;
uint64_t mSeekPos;
volatile bool mVideoEnded;
volatile bool mPaused;
volatile bool mQuit;
std::atomic<bool> mVideoEnded;
std::atomic<bool> mPaused;
std::atomic<bool> mQuit;
};
}

@ -214,6 +214,16 @@
<Property key="Caption" value="#{sControlsMenu1}"/>
</Widget>
<Widget type="HBox" skin="" position="4 224 300 24" align="Left Bottom">
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Bottom">
<UserString key="SettingCategory" value="Input"/>
<UserString key="SettingName" value="invert x axis"/>
<UserString key="SettingType" value="CheckButton"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" position="28 4 78 16" align="Left Bottom">
<Property key="Caption" value="Invert X Axis"/>
</Widget>
</Widget>
<Widget type="HBox" skin="" position="4 254 300 24" align="Left Bottom">
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Bottom">
<UserString key="SettingCategory" value="Input"/>
<UserString key="SettingName" value="invert y axis"/>
@ -223,10 +233,10 @@
<Property key="Caption" value="#{sMouseFlip}"/>
</Widget>
</Widget>
<Widget type="TextBox" skin="NormalText" position="4 254 336 18" align="Left Bottom">
<Widget type="TextBox" skin="NormalText" position="4 284 336 18" align="Left Bottom">
<Property key="Caption" value="Camera Sensitivity"/>
</Widget>
<Widget type="MWScrollBar" skin="MW_HScroll" position="4 278 336 18" align="HStretch Bottom">
<Widget type="MWScrollBar" skin="MW_HScroll" position="4 308 336 18" align="HStretch Bottom">
<Property key="Range" value="10000"/>
<Property key="Page" value="300"/>
<UserString key="SettingType" value="Slider"/>
@ -236,11 +246,11 @@
<UserString key="SettingMin" value="0.2"/>
<UserString key="SettingMax" value="5.0"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="4 302 336 18" align="Left Bottom">
<Widget type="TextBox" skin="SandText" position="4 332 336 18" align="Left Bottom">
<Property key="Caption" value="#{sLow}"/>
<Property key="TextAlign" value="Left"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="4 302 336 18" align="Right Bottom">
<Widget type="TextBox" skin="SandText" position="4 332 336 18" align="Right Bottom">
<Property key="Caption" value="#{sHigh}"/>
<Property key="TextAlign" value="Right"/>
</Widget>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2015 Alexandre Moine <nobrakal@gmail.com>
Copyright 2017 Bret Curtis <psi29a@gmail.com>
Copyright 2018 Bret Curtis <psi29a@gmail.com>
-->
<component type="desktop">
<id>org.openmw.desktop</id>
@ -43,9 +43,9 @@ Copyright 2017 Bret Curtis <psi29a@gmail.com>
<category>RolePlaying</category>
</categories>
<releases>
<release version="0.46.0" date="2017-12-05"/>
<release version="@OPENMW_VERSION@" date="@OPENMW_VERSION_COMMITDATE@"/>
</releases>
<url type="homepage">https://openmw.org</url>
<url type="bugtracker">https://bugs.openmw.org/</url>
<url type="bugtracker">https://gitlab.com/OpenMW/openmw/issues</url>
<url type="faq">https://openmw.org/faq/</url>
</component>

@ -333,6 +333,9 @@ camera sensitivity = 1.0
# (>0.0, Because it's a multiplier values should be near 1.0)
camera y multiplier = 1.0
# Invert the horizontal axis while not in GUI mode.
invert x axis = false
# Invert the vertical axis while not in GUI mode.
invert y axis = false

Loading…
Cancel
Save