mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-10-05 11:56:31 +00:00
Add OpenMW commits up to 30 May 2020
# Conflicts: # CMakeLists.txt # apps/openmw/mwbase/windowmanager.hpp # apps/openmw/mwgui/windowmanagerimp.hpp # apps/openmw/mwmechanics/actors.cpp # apps/openmw/mwmechanics/actors.hpp # apps/openmw/mwscript/interpretercontext.cpp
This commit is contained in:
commit
36a2308acd
109 changed files with 1620 additions and 1778 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -32,6 +32,7 @@ cmake-build-*
|
||||||
## qt-creator
|
## qt-creator
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
.vs
|
.vs
|
||||||
|
.vscode
|
||||||
|
|
||||||
## resources
|
## resources
|
||||||
data
|
data
|
||||||
|
|
|
@ -6,15 +6,22 @@
|
||||||
Bug #3676: NiParticleColorModifier isn't applied properly
|
Bug #3676: NiParticleColorModifier isn't applied properly
|
||||||
Bug #4774: Guards are ignorant of an invisible player that tries to attack them
|
Bug #4774: Guards are ignorant of an invisible player that tries to attack them
|
||||||
Bug #5108: Savegame bloating due to inefficient fog textures format
|
Bug #5108: Savegame bloating due to inefficient fog textures format
|
||||||
|
Bug #5165: Active spells should use real time intead of timestamps
|
||||||
Bug #5358: ForceGreeting always resets the dialogue window completely
|
Bug #5358: ForceGreeting always resets the dialogue window completely
|
||||||
Bug #5363: Enchantment autocalc not always 0/1
|
Bug #5363: Enchantment autocalc not always 0/1
|
||||||
Bug #5364: Script fails/stops if trying to startscript an unknown script
|
Bug #5364: Script fails/stops if trying to startscript an unknown script
|
||||||
Bug #5367: Selecting a spell on an enchanted item per hotkey always plays the equip sound
|
Bug #5367: Selecting a spell on an enchanted item per hotkey always plays the equip sound
|
||||||
Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures
|
Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures
|
||||||
Bug #5370: Opening an unlocked but trapped door uses the key
|
Bug #5370: Opening an unlocked but trapped door uses the key
|
||||||
|
Bug #5397: NPC greeting does not reset if you leave + reenter area
|
||||||
Bug #5400: Editor: Verifier checks race of non-skin bodyparts
|
Bug #5400: Editor: Verifier checks race of non-skin bodyparts
|
||||||
Bug #5415: Environment maps in ebony cuirass and HiRez Armors Indoril cuirass don't work
|
Bug #5415: Environment maps in ebony cuirass and HiRez Armors Indoril cuirass don't work
|
||||||
Bug #5416: Junk non-node records before the root node are not handled gracefully
|
Bug #5416: Junk non-node records before the root node are not handled gracefully
|
||||||
|
Bug #5424: Creatures do not headtrack player
|
||||||
|
Bug #5425: Poison effect only appears for one frame
|
||||||
|
Bug #5427: GetDistance unknown ID error is misleading
|
||||||
|
Bug #5435: Enemies can't hurt the player when collision is off
|
||||||
|
Bug #5441: Enemies can't push a player character when in critical strike stance
|
||||||
Feature #5362: Show the soul gems' trapped soul in count dialog
|
Feature #5362: Show the soul gems' trapped soul in count dialog
|
||||||
|
|
||||||
0.46.0
|
0.46.0
|
||||||
|
@ -188,8 +195,8 @@
|
||||||
Bug #5158: Objects without a name don't fallback to their ID
|
Bug #5158: Objects without a name don't fallback to their ID
|
||||||
Bug #5159: NiMaterialColorController can only control the diffuse color
|
Bug #5159: NiMaterialColorController can only control the diffuse color
|
||||||
Bug #5161: Creature companions can't be activated when they are knocked down
|
Bug #5161: Creature companions can't be activated when they are knocked down
|
||||||
Bug #5164: Faction owned items handling is incorrect
|
|
||||||
Bug #5163: UserData is not copied during node cloning
|
Bug #5163: UserData is not copied during node cloning
|
||||||
|
Bug #5164: Faction owned items handling is incorrect
|
||||||
Bug #5166: Scripts still should be executed after player's death
|
Bug #5166: Scripts still should be executed after player's death
|
||||||
Bug #5167: Player can select and cast spells before magic menu is enabled
|
Bug #5167: Player can select and cast spells before magic menu is enabled
|
||||||
Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change
|
Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change
|
||||||
|
|
26
CI/ActivateMSVC.ps1
Normal file
26
CI/ActivateMSVC.ps1
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
& "${env:COMSPEC}" /c ActivateMSVC.bat "&&" set | ForEach-Object {
|
||||||
|
$name, $value = $_ -split '=', 2
|
||||||
|
Set-Content env:\"$name" $value
|
||||||
|
}
|
||||||
|
|
||||||
|
$MissingTools = $false
|
||||||
|
$tools = "cl", "link", "rc", "mt", "awooga"
|
||||||
|
$descriptions = "MSVC Compiler", "MSVC Linker", "MS Windows Resource Compiler", "MS Windows Manifest Tool", "A made up command"
|
||||||
|
for ($i = 0; $i -lt $tools.Length; $i++) {
|
||||||
|
$present = $true
|
||||||
|
try {
|
||||||
|
Get-Command $tools[$i] *>&1 | Out-Null
|
||||||
|
$present = $present -and $?
|
||||||
|
} catch {
|
||||||
|
$present = $false
|
||||||
|
}
|
||||||
|
if (!$present) {
|
||||||
|
Write-Warning "$($tools[$i]) ($($descriptions[$i])) missing."
|
||||||
|
$MissingTools = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($MissingTools) {
|
||||||
|
Write-Error "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
|
||||||
|
exit 1
|
||||||
|
}
|
76
CI/activate_msvc.sh
Normal file
76
CI/activate_msvc.sh
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
echo "Error: Script not sourced."
|
||||||
|
echo "You must source this script for it to work, i.e. "
|
||||||
|
echo "source ./activate_msvc.sh"
|
||||||
|
echo "or"
|
||||||
|
echo ". ./activate_msvc.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v unixPathAsWindows >/dev/null 2>&1 || function unixPathAsWindows {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then
|
||||||
|
cygpath -w $1
|
||||||
|
else
|
||||||
|
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function windowsSystemPathAsUnix {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then
|
||||||
|
cygpath -u -p $1
|
||||||
|
else
|
||||||
|
IFS=';' read -r -a paths <<< "$1"
|
||||||
|
declare -a convertedPaths
|
||||||
|
for entry in paths; do
|
||||||
|
convertedPaths+=(windowsPathAsUnix $entry)
|
||||||
|
done
|
||||||
|
convertedPath=printf ":%s" ${convertedPaths[@]}
|
||||||
|
echo ${convertedPath:1}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# capture CMD environment so we know what's been changed
|
||||||
|
declare -A originalCmdEnv
|
||||||
|
originalIFS="$IFS"
|
||||||
|
IFS=$'\n\r'
|
||||||
|
for pair in $(cmd //c "set"); do
|
||||||
|
IFS='=' read -r -a separatedPair <<< "${pair}"
|
||||||
|
originalCmdEnv["${separatedPair[0]}"]="${separatedPair[1]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# capture CMD environment in a shell with MSVC activated
|
||||||
|
cmdEnv="$(cmd //c "$(unixPathAsWindows "$(dirname "${BASH_SOURCE[0]}")")\ActivateMSVC.bat" "&&" set)"
|
||||||
|
|
||||||
|
declare -A cmdEnvChanges
|
||||||
|
for pair in $cmdEnv; do
|
||||||
|
if [ -n "$pair" ]; then
|
||||||
|
IFS='=' read -r -a separatedPair <<< "${pair}"
|
||||||
|
key="${separatedPair[0]}"
|
||||||
|
value="${separatedPair[1]}"
|
||||||
|
if ! [ ${originalCmdEnv[$key]+_} ] || [ "${originalCmdEnv[$key]}" != "$value" ]; then
|
||||||
|
if [ $key != 'PATH' ] && [ $key != 'path' ] && [ $key != 'Path' ]; then
|
||||||
|
export "$key=$value"
|
||||||
|
else
|
||||||
|
export PATH=$(windowsSystemPathAsUnix $value)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
MISSINGTOOLS=0
|
||||||
|
|
||||||
|
command -v cl >/dev/null 2>&1 || { echo "Error: cl (MSVC Compiler) missing."; MISSINGTOOLS=1; }
|
||||||
|
command -v link >/dev/null 2>&1 || { echo "Error: link (MSVC Linker) missing."; MISSINGTOOLS=1; }
|
||||||
|
command -v rc >/dev/null 2>&1 || { echo "Error: rc (MS Windows Resource Compiler) missing."; MISSINGTOOLS=1; }
|
||||||
|
command -v mt >/dev/null 2>&1 || { echo "Error: mt (MS Windows Manifest Tool) missing."; MISSINGTOOLS=1; }
|
||||||
|
|
||||||
|
if [ $MISSINGTOOLS -ne 0 ]; then
|
||||||
|
echo "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS="$originalIFS"
|
|
@ -1,25 +1,50 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -x # turn-on for debugging
|
# set -x # turn-on for debugging
|
||||||
|
|
||||||
|
function wrappedExit {
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
exit $1
|
||||||
|
else
|
||||||
|
return $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
MISSINGTOOLS=0
|
MISSINGTOOLS=0
|
||||||
|
|
||||||
command -v 7z >/dev/null 2>&1 || { echo "Error: 7z (7zip) is not on the path."; MISSINGTOOLS=1; }
|
command -v 7z >/dev/null 2>&1 || { echo "Error: 7z (7zip) is not on the path."; MISSINGTOOLS=1; }
|
||||||
command -v cmake >/dev/null 2>&1 || { echo "Error: cmake (CMake) is not on the path."; MISSINGTOOLS=1; }
|
command -v cmake >/dev/null 2>&1 || { echo "Error: cmake (CMake) is not on the path."; MISSINGTOOLS=1; }
|
||||||
|
command -v python >/dev/null 2>&1 || { echo "Warning: Python is not on the path, automatic Qt installation impossible."; }
|
||||||
|
|
||||||
if [ $MISSINGTOOLS -ne 0 ]; then
|
if [ $MISSINGTOOLS -ne 0 ]; then
|
||||||
exit 1
|
wrappedExit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
WORKINGDIR="$(pwd)"
|
WORKINGDIR="$(pwd)"
|
||||||
case "$WORKINGDIR" in
|
case "$WORKINGDIR" in
|
||||||
*[[:space:]]*)
|
*[[:space:]]*)
|
||||||
echo "Error: Working directory contains spaces."
|
echo "Error: Working directory contains spaces."
|
||||||
exit 1
|
wrappedExit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
function windowsPathAsUnix {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then
|
||||||
|
cygpath -u $1
|
||||||
|
else
|
||||||
|
echo "$1" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function unixPathAsWindows {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then
|
||||||
|
cygpath -w $1
|
||||||
|
else
|
||||||
|
echo "$1" | sed "s,^/\([^/]\)/,\\1:/," | sed "s,/,\\\\,g"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
APPVEYOR=${APPVEYOR:-}
|
APPVEYOR=${APPVEYOR:-}
|
||||||
CI=${CI:-}
|
CI=${CI:-}
|
||||||
STEP=${STEP:-}
|
STEP=${STEP:-}
|
||||||
|
@ -32,11 +57,19 @@ KEEP=""
|
||||||
UNITY_BUILD=""
|
UNITY_BUILD=""
|
||||||
VS_VERSION=""
|
VS_VERSION=""
|
||||||
NMAKE=""
|
NMAKE=""
|
||||||
|
NINJA=""
|
||||||
|
PDBS=""
|
||||||
PLATFORM=""
|
PLATFORM=""
|
||||||
CONFIGURATION=""
|
CONFIGURATION=""
|
||||||
TEST_FRAMEWORK=""
|
TEST_FRAMEWORK=""
|
||||||
GOOGLE_INSTALL_ROOT=""
|
GOOGLE_INSTALL_ROOT=""
|
||||||
INSTALL_PREFIX="."
|
INSTALL_PREFIX="."
|
||||||
|
BULLET_DOUBLE=""
|
||||||
|
BULLET_DBL=""
|
||||||
|
BULLET_DBL_DISPLAY="Single precision"
|
||||||
|
|
||||||
|
ACTIVATE_MSVC=""
|
||||||
|
SINGLE_CONFIG=""
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
ARGSTR=$1
|
ARGSTR=$1
|
||||||
|
@ -45,7 +78,7 @@ while [ $# -gt 0 ]; do
|
||||||
if [ ${ARGSTR:0:1} != "-" ]; then
|
if [ ${ARGSTR:0:1} != "-" ]; then
|
||||||
echo "Unknown argument $ARGSTR"
|
echo "Unknown argument $ARGSTR"
|
||||||
echo "Try '$0 -h'"
|
echo "Try '$0 -h'"
|
||||||
exit 1
|
wrappedExit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for (( i=1; i<${#ARGSTR}; i++ )); do
|
for (( i=1; i<${#ARGSTR}; i++ )); do
|
||||||
|
@ -57,6 +90,9 @@ while [ $# -gt 0 ]; do
|
||||||
d )
|
d )
|
||||||
SKIP_DOWNLOAD=true ;;
|
SKIP_DOWNLOAD=true ;;
|
||||||
|
|
||||||
|
D )
|
||||||
|
BULLET_DOUBLE=true ;;
|
||||||
|
|
||||||
e )
|
e )
|
||||||
SKIP_EXTRACT=true ;;
|
SKIP_EXTRACT=true ;;
|
||||||
|
|
||||||
|
@ -73,10 +109,16 @@ while [ $# -gt 0 ]; do
|
||||||
n )
|
n )
|
||||||
NMAKE=true ;;
|
NMAKE=true ;;
|
||||||
|
|
||||||
|
N )
|
||||||
|
NINJA=true ;;
|
||||||
|
|
||||||
p )
|
p )
|
||||||
PLATFORM=$1
|
PLATFORM=$1
|
||||||
shift ;;
|
shift ;;
|
||||||
|
|
||||||
|
P )
|
||||||
|
PDBS=true ;;
|
||||||
|
|
||||||
c )
|
c )
|
||||||
CONFIGURATION=$1
|
CONFIGURATION=$1
|
||||||
shift ;;
|
shift ;;
|
||||||
|
@ -96,6 +138,8 @@ Options:
|
||||||
Set the configuration, can also be set with environment variable CONFIGURATION.
|
Set the configuration, can also be set with environment variable CONFIGURATION.
|
||||||
-d
|
-d
|
||||||
Skip checking the downloads.
|
Skip checking the downloads.
|
||||||
|
-D
|
||||||
|
Use double-precision Bullet
|
||||||
-e
|
-e
|
||||||
Skip extracting dependencies.
|
Skip extracting dependencies.
|
||||||
-h
|
-h
|
||||||
|
@ -111,25 +155,33 @@ Options:
|
||||||
-v <2013/2015/2017/2019>
|
-v <2013/2015/2017/2019>
|
||||||
Choose the Visual Studio version to use.
|
Choose the Visual Studio version to use.
|
||||||
-n
|
-n
|
||||||
Produce NMake makefiles instead of a Visual Studio solution.
|
Produce NMake makefiles instead of a Visual Studio solution. Cannout be used with -N.
|
||||||
|
-N
|
||||||
|
Produce Ninja (multi-config if CMake is new enough to support it) files instead of a Visual Studio solution. Cannot be used with -n..
|
||||||
|
-P
|
||||||
|
Download debug symbols where available
|
||||||
-V
|
-V
|
||||||
Run verbosely
|
Run verbosely
|
||||||
-i
|
-i
|
||||||
CMake install prefix
|
CMake install prefix
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
wrappedExit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
echo "Unknown argument $ARG."
|
echo "Unknown argument $ARG."
|
||||||
echo "Try '$0 -h'"
|
echo "Try '$0 -h'"
|
||||||
exit 1 ;;
|
wrappedExit 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -n "$NMAKE" ]; then
|
if [ -n "$NMAKE" ] || [ -n "$NINJA" ]; 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; }
|
if [ -n "$NMAKE" ] && [ -n "$NINJA" ]; then
|
||||||
|
echo "Cannout run in NMake and Ninja mode at the same time."
|
||||||
|
wrappedExit 1
|
||||||
|
fi
|
||||||
|
ACTIVATE_MSVC=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
|
@ -139,7 +191,7 @@ fi
|
||||||
if [ -z $APPVEYOR ]; then
|
if [ -z $APPVEYOR ]; then
|
||||||
echo "Running prebuild outside of Appveyor."
|
echo "Running prebuild outside of Appveyor."
|
||||||
|
|
||||||
DIR=$(echo "$0" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
|
DIR=$(windowsPathAsUnix "${BASH_SOURCE[0]}")
|
||||||
cd $(dirname "$DIR")/..
|
cd $(dirname "$DIR")/..
|
||||||
else
|
else
|
||||||
echo "Running prebuild in Appveyor."
|
echo "Running prebuild in Appveyor."
|
||||||
|
@ -264,6 +316,7 @@ case $VS_VERSION in
|
||||||
MSVC_REAL_VER="16"
|
MSVC_REAL_VER="16"
|
||||||
MSVC_VER="14.2"
|
MSVC_VER="14.2"
|
||||||
MSVC_YEAR="2015"
|
MSVC_YEAR="2015"
|
||||||
|
MSVC_REAL_YEAR="2019"
|
||||||
MSVC_DISPLAY_YEAR="2019"
|
MSVC_DISPLAY_YEAR="2019"
|
||||||
BOOST_VER="1.71.0"
|
BOOST_VER="1.71.0"
|
||||||
BOOST_VER_URL="1_71_0"
|
BOOST_VER_URL="1_71_0"
|
||||||
|
@ -276,6 +329,7 @@ case $VS_VERSION in
|
||||||
MSVC_REAL_VER="15"
|
MSVC_REAL_VER="15"
|
||||||
MSVC_VER="14.1"
|
MSVC_VER="14.1"
|
||||||
MSVC_YEAR="2015"
|
MSVC_YEAR="2015"
|
||||||
|
MSVC_REAL_YEAR="2017"
|
||||||
MSVC_DISPLAY_YEAR="2017"
|
MSVC_DISPLAY_YEAR="2017"
|
||||||
BOOST_VER="1.67.0"
|
BOOST_VER="1.67.0"
|
||||||
BOOST_VER_URL="1_67_0"
|
BOOST_VER_URL="1_67_0"
|
||||||
|
@ -288,6 +342,7 @@ case $VS_VERSION in
|
||||||
MSVC_REAL_VER="14"
|
MSVC_REAL_VER="14"
|
||||||
MSVC_VER="14.0"
|
MSVC_VER="14.0"
|
||||||
MSVC_YEAR="2015"
|
MSVC_YEAR="2015"
|
||||||
|
MSVC_REAL_YEAR="2015"
|
||||||
MSVC_DISPLAY_YEAR="2015"
|
MSVC_DISPLAY_YEAR="2015"
|
||||||
BOOST_VER="1.67.0"
|
BOOST_VER="1.67.0"
|
||||||
BOOST_VER_URL="1_67_0"
|
BOOST_VER_URL="1_67_0"
|
||||||
|
@ -295,15 +350,8 @@ case $VS_VERSION in
|
||||||
;;
|
;;
|
||||||
|
|
||||||
12|12.0|2013 )
|
12|12.0|2013 )
|
||||||
GENERATOR="Visual Studio 12 2013"
|
echo "Visual Studio 2013 is no longer supported"
|
||||||
TOOLSET="vc120"
|
exit 1
|
||||||
MSVC_REAL_VER="12"
|
|
||||||
MSVC_VER="12.0"
|
|
||||||
MSVC_YEAR="2013"
|
|
||||||
MSVC_DISPLAY_YEAR="2013"
|
|
||||||
BOOST_VER="1.58.0"
|
|
||||||
BOOST_VER_URL="1_58_0"
|
|
||||||
BOOST_VER_SDK="105800"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -322,7 +370,7 @@ case $PLATFORM in
|
||||||
|
|
||||||
* )
|
* )
|
||||||
echo "Unknown platform $PLATFORM."
|
echo "Unknown platform $PLATFORM."
|
||||||
exit 1
|
wrappedExit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -349,9 +397,18 @@ fi
|
||||||
|
|
||||||
if [ -n "$NMAKE" ]; then
|
if [ -n "$NMAKE" ]; then
|
||||||
GENERATOR="NMake Makefiles"
|
GENERATOR="NMake Makefiles"
|
||||||
|
SINGLE_CONFIG=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $MSVC_REAL_VER -ge 16 ]; then
|
if [ -n "$NINJA" ]; then
|
||||||
|
GENERATOR="Ninja Multi-Config"
|
||||||
|
if ! cmake -E capabilities | grep -F "$GENERATOR" > /dev/null; then
|
||||||
|
SINGLE_CONFIG=true
|
||||||
|
GENERATOR="Ninja"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $MSVC_REAL_VER -ge 16 ] && [ -z "$NMAKE" ] && [ -z "$NINJA" ]; then
|
||||||
if [ $BITS -eq 64 ]; then
|
if [ $BITS -eq 64 ]; then
|
||||||
add_cmake_opts "-G\"$GENERATOR\" -A x64"
|
add_cmake_opts "-G\"$GENERATOR\" -A x64"
|
||||||
else
|
else
|
||||||
|
@ -361,7 +418,7 @@ else
|
||||||
add_cmake_opts "-G\"$GENERATOR\""
|
add_cmake_opts "-G\"$GENERATOR\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$NMAKE" ]; then
|
if [ -n "$SINGLE_CONFIG" ]; then
|
||||||
add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}"
|
add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -369,6 +426,12 @@ if ! [ -z $UNITY_BUILD ]; then
|
||||||
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
|
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$BULLET_DOUBLE" ]; then
|
||||||
|
BULLET_DBL="-double"
|
||||||
|
BULLET_DBL_DISPLAY="Double precision"
|
||||||
|
add_cmake_opts "-DBULLET_USE_DOUBLES=True"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
|
echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}"
|
||||||
|
@ -393,45 +456,54 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bullet
|
# Bullet
|
||||||
download "Bullet 2.87" \
|
download "Bullet 2.89 (${BULLET_DBL_DISPLAY})" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
"https://rgw.ctrl-c.liu.se/openmw/Deps/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" \
|
||||||
"Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z"
|
"Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z"
|
||||||
|
|
||||||
# FFmpeg
|
# FFmpeg
|
||||||
download "FFmpeg 3.2.4" \
|
download "FFmpeg 4.2.2" \
|
||||||
"https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \
|
"https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-4.2.2-win${BITS}-shared.zip" \
|
||||||
"ffmpeg-3.2.4-win${BITS}.zip" \
|
"ffmpeg-4.2.2-win${BITS}.zip" \
|
||||||
"https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \
|
"https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-4.2.2-win${BITS}-dev.zip" \
|
||||||
"ffmpeg-3.2.4-dev-win${BITS}.zip"
|
"ffmpeg-4.2.2-dev-win${BITS}.zip"
|
||||||
|
|
||||||
# MyGUI
|
# MyGUI
|
||||||
download "MyGUI 3.2.2" \
|
download "MyGUI 3.4.0" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
"https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
|
||||||
"MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z"
|
"MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
|
||||||
|
|
||||||
|
if [ -n "$PDBS" ]; then
|
||||||
|
download "MyGUI symbols" \
|
||||||
|
"https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
|
||||||
|
"MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
|
||||||
|
fi
|
||||||
|
|
||||||
# OpenAL
|
# OpenAL
|
||||||
download "OpenAL-Soft 1.19.1" \
|
download "OpenAL-Soft 1.20.1" \
|
||||||
"http://openal-soft.org/openal-binaries/openal-soft-1.19.1-bin.zip" \
|
"http://openal-soft.org/openal-binaries/openal-soft-1.20.1-bin.zip" \
|
||||||
"OpenAL-Soft-1.19.1.zip"
|
"OpenAL-Soft-1.20.1.zip"
|
||||||
|
|
||||||
# OSG
|
# OSG
|
||||||
download "OpenSceneGraph 3.4.1-scrawl" \
|
download "OpenSceneGraph 3.6.5" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
"https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \
|
||||||
"OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z"
|
"OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z"
|
||||||
|
|
||||||
|
if [ -n "$PDBS" ]; then
|
||||||
|
download "OpenSceneGraph symbols" \
|
||||||
|
"https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \
|
||||||
|
"OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z"
|
||||||
|
fi
|
||||||
|
|
||||||
# Qt
|
# Qt
|
||||||
if [ -z $APPVEYOR ]; then
|
if [ -z $APPVEYOR ]; then
|
||||||
if [ $BITS == "64" ]; then
|
if [ "${MSVC_REAL_YEAR}" = "2015" ] && [ "${BITS}" = "32" ]; then
|
||||||
QT_SUFFIX="_64"
|
echo "Qt no longer provides MSVC2015 Win32 packages, switch to 64-bit or a newer Visual Studio. Sorry."
|
||||||
else
|
exit 1
|
||||||
QT_SUFFIX=""
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
download "Qt 5.7.0" \
|
download "AQt installer" \
|
||||||
"https://download.qt.io/new_archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
|
"https://files.pythonhosted.org/packages/f3/bb/aee972f08deecca31bfc46b5aedfad1ce6c7f3aaf1288d685e4a914b53ac/aqtinstall-0.8-py2.py3-none-any.whl" \
|
||||||
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
|
"aqtinstall-0.8-py2.py3-none-any.whl"
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
|
||||||
"qt-5-install.qs"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# SDL2
|
# SDL2
|
||||||
|
@ -456,7 +528,13 @@ cd .. #/..
|
||||||
BUILD_DIR="MSVC${MSVC_DISPLAY_YEAR}_${BITS}"
|
BUILD_DIR="MSVC${MSVC_DISPLAY_YEAR}_${BITS}"
|
||||||
|
|
||||||
if [ -n "$NMAKE" ]; then
|
if [ -n "$NMAKE" ]; then
|
||||||
BUILD_DIR="${BUILD_DIR}_NMake_${BUILD_CONFIG}"
|
BUILD_DIR="${BUILD_DIR}_NMake"
|
||||||
|
elif [ -n "$NINJA" ]; then
|
||||||
|
BUILD_DIR="${BUILD_DIR}_Ninja"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SINGLE_CONFIG" ]; then
|
||||||
|
BUILD_DIR="${BUILD_DIR}_${BUILD_CONFIG}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z $KEEP ]; then
|
if [ -z $KEEP ]; then
|
||||||
|
@ -494,10 +572,10 @@ fi
|
||||||
# We work around this by installing to root of the current working drive and then move it to our deps
|
# We work around this by installing to root of the current working drive and then move it to our deps
|
||||||
# get the current working drive's root, we'll install to that temporarily
|
# get the current working drive's root, we'll install to that temporarily
|
||||||
CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp"
|
CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp"
|
||||||
CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
|
CWD_DRIVE_ROOT_BASH=$(windowsPathAsUnix "$CWD_DRIVE_ROOT")
|
||||||
if [ -d CWD_DRIVE_ROOT_BASH ]; then
|
if [ -d CWD_DRIVE_ROOT_BASH ]; then
|
||||||
printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. ";
|
printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. ";
|
||||||
exit 1;
|
wrappedExit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION ${BOOST_VER_SDK}" Boost/boost/version.hpp > /dev/null; then
|
if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION ${BOOST_VER_SDK}" Boost/boost/version.hpp > /dev/null; then
|
||||||
|
@ -533,15 +611,15 @@ fi
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# Bullet
|
# Bullet
|
||||||
printf "Bullet 2.87... "
|
printf "Bullet 2.89 (${BULLET_DBL_DISPLAY})... "
|
||||||
{
|
{
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
if [ -d Bullet ]; then
|
if [ -d Bullet ]; then
|
||||||
printf -- "Exists. (No version checking) "
|
printf -- "Exists. (No version checking) "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf Bullet
|
rm -rf Bullet
|
||||||
eval 7z x -y "${DEPS}/Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" $STRIP
|
||||||
mv "Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}" Bullet
|
mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}" Bullet
|
||||||
fi
|
fi
|
||||||
export BULLET_ROOT="$(real_pwd)/Bullet"
|
export BULLET_ROOT="$(real_pwd)/Bullet"
|
||||||
echo Done.
|
echo Done.
|
||||||
|
@ -549,21 +627,21 @@ printf "Bullet 2.87... "
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# FFmpeg
|
# FFmpeg
|
||||||
printf "FFmpeg 3.2.4... "
|
printf "FFmpeg 4.2.2... "
|
||||||
{
|
{
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then
|
if [ -d FFmpeg ] && grep "4.2.2" FFmpeg/README.txt > /dev/null; then
|
||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf FFmpeg
|
rm -rf FFmpeg
|
||||||
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-win${BITS}.zip" $STRIP
|
eval 7z x -y "${DEPS}/ffmpeg-4.2.2-win${BITS}.zip" $STRIP
|
||||||
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-dev-win${BITS}.zip" $STRIP
|
eval 7z x -y "${DEPS}/ffmpeg-4.2.2-dev-win${BITS}.zip" $STRIP
|
||||||
mv "ffmpeg-3.2.4-win${BITS}-shared" FFmpeg
|
mv "ffmpeg-4.2.2-win${BITS}-shared" FFmpeg
|
||||||
cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/
|
cp -r "ffmpeg-4.2.2-win${BITS}-dev/"* FFmpeg/
|
||||||
rm -rf "ffmpeg-3.2.4-win${BITS}-dev"
|
rm -rf "ffmpeg-4.2.2-win${BITS}-dev"
|
||||||
fi
|
fi
|
||||||
export FFMPEG_HOME="$(real_pwd)/FFmpeg"
|
export FFMPEG_HOME="$(real_pwd)/FFmpeg"
|
||||||
add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll
|
add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-58,avformat-58,avutil-56,swresample-3,swscale-5}.dll
|
||||||
if [ $BITS -eq 32 ]; then
|
if [ $BITS -eq 32 ]; then
|
||||||
add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\""
|
add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\""
|
||||||
fi
|
fi
|
||||||
|
@ -572,62 +650,66 @@ printf "FFmpeg 3.2.4... "
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# MyGUI
|
# MyGUI
|
||||||
printf "MyGUI 3.2.2... "
|
printf "MyGUI 3.4.0... "
|
||||||
{
|
{
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
if [ -d MyGUI ] && \
|
if [ -d MyGUI ] && \
|
||||||
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||||
grep "MYGUI_VERSION_MINOR 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
grep "MYGUI_VERSION_MINOR 4" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||||
grep "MYGUI_VERSION_PATCH 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null
|
grep "MYGUI_VERSION_PATCH 0" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null
|
||||||
then
|
then
|
||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf MyGUI
|
rm -rf MyGUI
|
||||||
eval 7z x -y "${DEPS}/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
|
||||||
mv "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}" MyGUI
|
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
|
||||||
|
mv "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}" MyGUI
|
||||||
fi
|
fi
|
||||||
export MYGUI_HOME="$(real_pwd)/MyGUI"
|
export MYGUI_HOME="$(real_pwd)/MyGUI"
|
||||||
if [ $CONFIGURATION == "Debug" ]; then
|
if [ $CONFIGURATION == "Debug" ]; then
|
||||||
SUFFIX="_d"
|
SUFFIX="_d"
|
||||||
|
MYGUI_CONFIGURATION="Debug"
|
||||||
else
|
else
|
||||||
SUFFIX=""
|
SUFFIX=""
|
||||||
|
MYGUI_CONFIGURATION="RelWithDebInfo"
|
||||||
fi
|
fi
|
||||||
add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll"
|
add_runtime_dlls "$(pwd)/MyGUI/bin/${MYGUI_CONFIGURATION}/MyGUIEngine${SUFFIX}.dll"
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# OpenAL
|
# OpenAL
|
||||||
printf "OpenAL-Soft 1.19.1... "
|
printf "OpenAL-Soft 1.20.1... "
|
||||||
{
|
{
|
||||||
if [ -d openal-soft-1.19.1-bin ]; then
|
if [ -d openal-soft-1.20.1-bin ]; then
|
||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf openal-soft-1.19.1-bin
|
rm -rf openal-soft-1.20.1-bin
|
||||||
eval 7z x -y OpenAL-Soft-1.19.1.zip $STRIP
|
eval 7z x -y OpenAL-Soft-1.20.1.zip $STRIP
|
||||||
fi
|
fi
|
||||||
OPENAL_SDK="$(real_pwd)/openal-soft-1.19.1-bin"
|
OPENAL_SDK="$(real_pwd)/openal-soft-1.20.1-bin"
|
||||||
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
|
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
|
||||||
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib"
|
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib"
|
||||||
add_runtime_dlls "$(pwd)/openal-soft-1.19.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
|
add_runtime_dlls "$(pwd)/openal-soft-1.20.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# OSG
|
# OSG
|
||||||
printf "OSG 3.4.1-scrawl... "
|
printf "OSG 3.6.5... "
|
||||||
{
|
{
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
if [ -d OSG ] && \
|
if [ -d OSG ] && \
|
||||||
grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \
|
grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \
|
||||||
grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \
|
grep "OPENSCENEGRAPH_MINOR_VERSION 6" OSG/include/osg/Version > /dev/null && \
|
||||||
grep "OPENSCENEGRAPH_PATCH_VERSION 1" OSG/include/osg/Version > /dev/null
|
grep "OPENSCENEGRAPH_PATCH_VERSION 5" OSG/include/osg/Version > /dev/null
|
||||||
then
|
then
|
||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf OSG
|
rm -rf OSG
|
||||||
eval 7z x -y "${DEPS}/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" $STRIP
|
||||||
mv "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}" OSG
|
[ -n "$PDBS" ] && eval 7z x -y "${DEPS}/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" $STRIP
|
||||||
|
mv "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}" OSG
|
||||||
fi
|
fi
|
||||||
OSG_SDK="$(real_pwd)/OSG"
|
OSG_SDK="$(real_pwd)/OSG"
|
||||||
add_cmake_opts -DOSG_DIR="$OSG_SDK"
|
add_cmake_opts -DOSG_DIR="$OSG_SDK"
|
||||||
|
@ -636,17 +718,17 @@ printf "OSG 3.4.1-scrawl... "
|
||||||
else
|
else
|
||||||
SUFFIX=""
|
SUFFIX=""
|
||||||
fi
|
fi
|
||||||
add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng*}${SUFFIX}.dll \
|
add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng}${SUFFIX}.dll \
|
||||||
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll
|
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll
|
||||||
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll
|
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll
|
||||||
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll
|
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# Qt
|
# Qt
|
||||||
if [ -z $APPVEYOR ]; then
|
if [ -z $APPVEYOR ]; then
|
||||||
printf "Qt 5.7.0... "
|
printf "Qt 5.15.0... "
|
||||||
else
|
else
|
||||||
printf "Qt 5.13 AppVeyor... "
|
printf "Qt 5.13 AppVeyor... "
|
||||||
fi
|
fi
|
||||||
|
@ -658,21 +740,44 @@ fi
|
||||||
fi
|
fi
|
||||||
if [ -z $APPVEYOR ]; then
|
if [ -z $APPVEYOR ]; then
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
QT_SDK="$(real_pwd)/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}"
|
QT_SDK="$(real_pwd)/Qt/5.15.0/msvc${MSVC_REAL_YEAR}${SUFFIX}"
|
||||||
if [ -d Qt ] && head -n2 Qt/InstallationLog.txt | grep "5.7.0" > /dev/null; then
|
|
||||||
|
if [ -d 'Qt/5.15.0' ]; then
|
||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf Qt
|
pushd "$DEPS" > /dev/null
|
||||||
cp "${DEPS}/qt-5-install.qs" qt-install.qs
|
if ! [ -d 'aqt-venv' ]; then
|
||||||
sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" qt-install.qs
|
echo " Creating Virtualenv for aqt..."
|
||||||
sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs
|
eval python -m venv aqt-venv $STRIP
|
||||||
printf -- "(Installation might take a while) "
|
|
||||||
"${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent
|
|
||||||
mv qt-install.qs Qt/
|
|
||||||
echo Done.
|
|
||||||
printf " Cleaning up extraneous data... "
|
|
||||||
rm -r "$(real_pwd)/Qt/"{dist,Docs,Examples,Tools,vcredist,components.xml,MaintenanceTool.dat,MaintenanceTool.exe,MaintenanceTool.ini,network.xml,qt-install.qs}
|
|
||||||
fi
|
fi
|
||||||
|
if [ -d 'aqt-venv/bin' ]; then
|
||||||
|
VENV_BIN_DIR='bin'
|
||||||
|
elif [ -d 'aqt-venv/Scripts' ]; then
|
||||||
|
VENV_BIN_DIR='Scripts'
|
||||||
|
else
|
||||||
|
echo "Error: Failed to create virtualenv."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -e "aqt-venv/${VENV_BIN_DIR}/aqt" ]; then
|
||||||
|
echo " Installing aqt wheel into virtualenv..."
|
||||||
|
eval "aqt-venv/${VENV_BIN_DIR}/pip" install aqtinstall-0.8-py2.py3-none-any.whl $STRIP
|
||||||
|
fi
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf Qt
|
||||||
|
|
||||||
|
mkdir Qt
|
||||||
|
cd Qt
|
||||||
|
|
||||||
|
eval "${DEPS}/aqt-venv/${VENV_BIN_DIR}/aqt" install 5.15.0 windows desktop "win${BITS}_msvc${MSVC_REAL_YEAR}${SUFFIX}" $STRIP
|
||||||
|
|
||||||
|
printf " Cleaning up extraneous data... "
|
||||||
|
rm -rf Qt/{aqtinstall.log,Tools}
|
||||||
|
|
||||||
|
echo Done.
|
||||||
|
fi
|
||||||
|
|
||||||
cd $QT_SDK
|
cd $QT_SDK
|
||||||
add_cmake_opts -DDESIRED_QT_VERSION=5 \
|
add_cmake_opts -DDESIRED_QT_VERSION=5 \
|
||||||
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||||
|
@ -695,7 +800,7 @@ fi
|
||||||
else
|
else
|
||||||
SUFFIX=""
|
SUFFIX=""
|
||||||
fi
|
fi
|
||||||
DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
|
DIR=$(windowsPathAsUnix "${QT_SDK}")
|
||||||
add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
|
add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
|
||||||
add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll"
|
add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll"
|
||||||
echo Done.
|
echo Done.
|
||||||
|
@ -806,14 +911,15 @@ fi
|
||||||
#if [ -z $CI ]; then
|
#if [ -z $CI ]; then
|
||||||
echo "- Copying Runtime DLLs..."
|
echo "- Copying Runtime DLLs..."
|
||||||
DLL_PREFIX=""
|
DLL_PREFIX=""
|
||||||
if [ -z $NMAKE ]; then
|
if [ -z $SINGLE_CONFIG ]; then
|
||||||
mkdir -p $BUILD_CONFIG
|
mkdir -p $BUILD_CONFIG
|
||||||
DLL_PREFIX="$BUILD_CONFIG/"
|
DLL_PREFIX="$BUILD_CONFIG/"
|
||||||
fi
|
fi
|
||||||
for DLL in $RUNTIME_DLLS; do
|
for DLL in $RUNTIME_DLLS; do
|
||||||
TARGET="$(basename "$DLL")"
|
TARGET="$(basename "$DLL")"
|
||||||
if [[ "$DLL" == *":"* ]]; then
|
if [[ "$DLL" == *":"* ]]; then
|
||||||
IFS=':'; SPLIT=( ${DLL} ); unset IFS
|
originalIFS="$IFS"
|
||||||
|
IFS=':'; SPLIT=( ${DLL} ); IFS=$originalIFS
|
||||||
DLL=${SPLIT[0]}
|
DLL=${SPLIT[0]}
|
||||||
TARGET=${SPLIT[1]}
|
TARGET=${SPLIT[1]}
|
||||||
fi
|
fi
|
||||||
|
@ -822,10 +928,10 @@ fi
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
echo "- OSG Plugin DLLs..."
|
echo "- OSG Plugin DLLs..."
|
||||||
mkdir -p ${DLL_PREFIX}osgPlugins-3.4.1
|
mkdir -p ${DLL_PREFIX}osgPlugins-3.6.5
|
||||||
for DLL in $OSG_PLUGINS; do
|
for DLL in $OSG_PLUGINS; do
|
||||||
echo " $(basename $DLL)."
|
echo " $(basename $DLL)."
|
||||||
cp "$DLL" ${DLL_PREFIX}osgPlugins-3.4.1
|
cp "$DLL" ${DLL_PREFIX}osgPlugins-3.6.5
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
echo "- Qt Platform DLLs..."
|
echo "- Qt Platform DLLs..."
|
||||||
|
@ -836,6 +942,42 @@ fi
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
#fi
|
#fi
|
||||||
|
|
||||||
|
if ! [ -z $ACTIVATE_MSVC ]; then
|
||||||
|
echo -n "- Activating MSVC in the current shell... "
|
||||||
|
command -v vswhere >/dev/null 2>&1 || { echo "Error: vswhere is not on the path."; wrappedExit 1; }
|
||||||
|
|
||||||
|
MSVC_INSTALLATION_PATH=$(vswhere -legacy -version "[$MSVC_VER,$(awk "BEGIN { print $MSVC_REAL_VER + 1; exit }"))" -property installationPath)
|
||||||
|
if [ $MSVC_REAL_VER -ge 15 ]; then
|
||||||
|
echo "@\"${MSVC_INSTALLATION_PATH}\Common7\Tools\VsDevCmd.bat\" -no_logo -arch=$([ $BITS -eq 64 ] && echo "amd64" || echo "x86") -host_arch=$([ $(uname -m) == 'x86_64' ] && echo "amd64" || echo "x86")" > ActivateMSVC.bat
|
||||||
|
else
|
||||||
|
if [ $(uname -m) == 'x86_64' ]; then
|
||||||
|
if [ $BITS -eq 64 ]; then
|
||||||
|
compiler=amd64
|
||||||
|
else
|
||||||
|
compiler=amd64_x86
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $BITS -eq 64 ]; then
|
||||||
|
compiler=x86_amd64
|
||||||
|
else
|
||||||
|
compiler=x86
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "@\"${MSVC_INSTALLATION_PATH}\VC\vcvarsall.bat\" $compiler" > ActivateMSVC.bat
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "../CI/activate_msvc.sh" .
|
||||||
|
sed -i "s/\$MSVC_DISPLAY_YEAR/$MSVC_DISPLAY_YEAR/g" activate_msvc.sh
|
||||||
|
source ./activate_msvc.sh
|
||||||
|
|
||||||
|
cp "../CI/ActivateMSVC.ps1" .
|
||||||
|
sed -i "s/\$MSVC_DISPLAY_YEAR/$MSVC_DISPLAY_YEAR/g" ActivateMSVC.ps1
|
||||||
|
|
||||||
|
echo "done."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
printf -- "- Configuring... "
|
printf -- "- Configuring... "
|
||||||
else
|
else
|
||||||
|
@ -846,8 +988,34 @@ RET=$?
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
if [ $RET -eq 0 ]; then
|
if [ $RET -eq 0 ]; then
|
||||||
echo Done.
|
echo Done.
|
||||||
|
if [ -n $ACTIVATE_MSVC ]; then
|
||||||
|
echo
|
||||||
|
echo "Note: you must manually activate MSVC for the shell in which you want to do the build."
|
||||||
|
echo
|
||||||
|
echo "Some scripts have been created in the build directory to do so in an existing shell."
|
||||||
|
echo "Bash: source activate_msvc.sh"
|
||||||
|
echo "CMD: ActivateMSVC.bat"
|
||||||
|
echo "PowerShell: ActivateMSVC.ps1"
|
||||||
|
echo
|
||||||
|
echo "You may find options to launch a Development/Native Tools/Cross Tools shell in your start menu or Visual Studio."
|
||||||
|
echo
|
||||||
|
if [ $(uname -m) == 'x86_64' ]; then
|
||||||
|
if [ $BITS -eq 64 ]; then
|
||||||
|
inheritEnvironments=msvc_x64_x64
|
||||||
|
else
|
||||||
|
inheritEnvironments=msvc_x64
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $BITS -eq 64 ]; then
|
||||||
|
inheritEnvironments=msvc_x86_x64
|
||||||
|
else
|
||||||
|
inheritEnvironments=msvc_x86
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "In Visual Studio 15.3 (2017 Update 3) or later, try setting '\"inheritEnvironments\": [ \"$inheritEnvironments\" ]' in CMakeSettings.json to build in the IDE."
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo Failed.
|
echo Failed.
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
exit $RET
|
wrappedExit $RET
|
||||||
|
|
|
@ -11,6 +11,7 @@ option(BUILD_NIFTEST "Build nif file tester" ON)
|
||||||
option(BUILD_DOCS "Build documentation." OFF )
|
option(BUILD_DOCS "Build documentation." OFF )
|
||||||
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
||||||
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
|
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
|
||||||
|
option(BULLET_USE_DOUBLES "Use double precision for Bullet" OFF)
|
||||||
option(BUILD_OPENMW_MP "Build OpenMW-MP" ON)
|
option(BUILD_OPENMW_MP "Build OpenMW-MP" ON)
|
||||||
option(BUILD_BROWSER "Build tes3mp Server Browser" ON)
|
option(BUILD_BROWSER "Build tes3mp Server Browser" ON)
|
||||||
option(BUILD_MASTER "Build tes3mp Master Server" OFF)
|
option(BUILD_MASTER "Build tes3mp Master Server" OFF)
|
||||||
|
|
|
@ -15,6 +15,10 @@ set(GAME_HEADER
|
||||||
engine.hpp
|
engine.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (BULLET_USE_DOUBLES)
|
||||||
|
add_definitions(-DBT_USE_DOUBLE_PRECISION)
|
||||||
|
endif()
|
||||||
|
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
|
@ -41,7 +45,7 @@ add_openmw_dir (mwgui
|
||||||
itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
|
itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
|
||||||
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
||||||
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
||||||
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation
|
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwdialogue
|
add_openmw_dir (mwdialogue
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
@ -270,7 +271,7 @@ bool OMW::Engine::frame(float frametime)
|
||||||
osg::Timer_t afterWorldTick = osg::Timer::instance()->tick();
|
osg::Timer_t afterWorldTick = osg::Timer::instance()->tick();
|
||||||
|
|
||||||
// update GUI
|
// update GUI
|
||||||
mEnvironment.getWindowManager()->onFrame(frametime);
|
mEnvironment.getWindowManager()->update(frametime);
|
||||||
|
|
||||||
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||||
osg::Stats* stats = mViewer->getViewerStats();
|
osg::Stats* stats = mViewer->getViewerStats();
|
||||||
|
@ -292,12 +293,14 @@ bool OMW::Engine::frame(float frametime)
|
||||||
|
|
||||||
if (stats->collectStats("resource"))
|
if (stats->collectStats("resource"))
|
||||||
{
|
{
|
||||||
|
stats->setAttribute(frameNumber, "FrameNumber", frameNumber);
|
||||||
|
|
||||||
mResourceSystem->reportStats(frameNumber, stats);
|
mResourceSystem->reportStats(frameNumber, stats);
|
||||||
|
|
||||||
stats->setAttribute(frameNumber, "WorkQueue", mWorkQueue->getNumItems());
|
stats->setAttribute(frameNumber, "WorkQueue", mWorkQueue->getNumItems());
|
||||||
stats->setAttribute(frameNumber, "WorkThread", mWorkQueue->getNumActiveThreads());
|
stats->setAttribute(frameNumber, "WorkThread", mWorkQueue->getNumActiveThreads());
|
||||||
|
|
||||||
mEnvironment.getWorld()->getNavigator()->reportStats(frameNumber, *stats);
|
mEnvironment.reportStats(frameNumber, *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -891,6 +894,14 @@ void OMW::Engine::go()
|
||||||
mEnvironment.getWindowManager()->executeInConsole(mStartupScript);
|
mEnvironment.getWindowManager()->executeInConsole(mStartupScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ofstream stats;
|
||||||
|
if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE"))
|
||||||
|
{
|
||||||
|
stats.open(path, std::ios_base::out);
|
||||||
|
if (!stats)
|
||||||
|
Log(Debug::Warning) << "Failed to open file for stats: " << path;
|
||||||
|
}
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
osg::Timer frameTimer;
|
osg::Timer frameTimer;
|
||||||
double simulationTime = 0.0;
|
double simulationTime = 0.0;
|
||||||
|
@ -933,6 +944,12 @@ void OMW::Engine::go()
|
||||||
simulationTime += dt;
|
simulationTime += dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stats)
|
||||||
|
{
|
||||||
|
const auto frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||||
|
mViewer->getViewerStats()->report(stats, frameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
mEnvironment.limitFrameRate(frameTimer.time_s());
|
mEnvironment.limitFrameRate(frameTimer.time_s());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,3 +198,9 @@ const MWBase::Environment& MWBase::Environment::get()
|
||||||
assert (sThis);
|
assert (sThis);
|
||||||
return *sThis;
|
return *sThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWBase::Environment::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
mMechanicsManager->reportStats(frameNumber, stats);
|
||||||
|
mWorld->reportStats(frameNumber, stats);
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#ifndef GAME_BASE_ENVIRONMENT_H
|
#ifndef GAME_BASE_ENVIRONMENT_H
|
||||||
#define GAME_BASE_ENVIRONMENT_H
|
#define GAME_BASE_ENVIRONMENT_H
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Stats;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
class World;
|
class World;
|
||||||
|
@ -97,6 +102,8 @@ namespace MWBase
|
||||||
|
|
||||||
static const Environment& get();
|
static const Environment& get();
|
||||||
///< Return instance of this class.
|
///< Return instance of this class.
|
||||||
|
|
||||||
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace MWBase
|
||||||
virtual void resetIdleTime() = 0;
|
virtual void resetIdleTime() = 0;
|
||||||
|
|
||||||
virtual void executeAction(int action) = 0;
|
virtual void executeAction(int action) = 0;
|
||||||
|
|
||||||
|
virtual bool controlsDisabled() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,14 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
// For MWMechanics::GreetingState
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
|
class Stats;
|
||||||
class Vec3f;
|
class Vec3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +304,13 @@ namespace MWBase
|
||||||
virtual bool isAttackPreparing(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isAttackPreparing(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
||||||
|
|
||||||
|
virtual int getGreetingTimer(const MWWorld::Ptr& ptr) const = 0;
|
||||||
|
virtual float getAngleToPlayer(const MWWorld::Ptr& ptr) const = 0;
|
||||||
|
virtual MWMechanics::GreetingState getGreetingState(const MWWorld::Ptr& ptr) const = 0;
|
||||||
|
virtual bool isTurningToPlayer(const MWWorld::Ptr& ptr) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -327,13 +327,7 @@ namespace MWBase
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual void onFrame (float frameDuration) = 0;
|
virtual void update (float duration) = 0;
|
||||||
|
|
||||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
|
||||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
|
|
||||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
|
|
||||||
virtual SkillList getPlayerMinorSkills() = 0;
|
|
||||||
virtual SkillList getPlayerMajorSkills() = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches a GMST string from the store, if there is no setting with the given
|
* Fetches a GMST string from the store, if there is no setting with the given
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace osg
|
||||||
class Matrixf;
|
class Matrixf;
|
||||||
class Quat;
|
class Quat;
|
||||||
class Image;
|
class Image;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
|
@ -831,6 +832,8 @@ namespace MWBase
|
||||||
virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
||||||
|
|
||||||
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const = 0;
|
virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const = 0;
|
||||||
|
|
||||||
|
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,23 +105,32 @@ namespace MWGui
|
||||||
mGenerateClassSpecializations[0] = 0;
|
mGenerateClassSpecializations[0] = 0;
|
||||||
mGenerateClassSpecializations[1] = 0;
|
mGenerateClassSpecializations[1] = 0;
|
||||||
mGenerateClassSpecializations[2] = 0;
|
mGenerateClassSpecializations[2] = 0;
|
||||||
|
|
||||||
|
// Setup player stats
|
||||||
|
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||||
|
mPlayerAttributes.emplace(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue());
|
||||||
|
|
||||||
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
|
mPlayerSkillValues.emplace(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
|
||||||
if (mReviewDialog)
|
|
||||||
{
|
{
|
||||||
static const char *ids[] =
|
static const char *ids[] =
|
||||||
{
|
{
|
||||||
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
|
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4",
|
||||||
"AttribVal6", "AttribVal7", "AttribVal8",
|
"AttribVal5", "AttribVal6", "AttribVal7", "AttribVal8", 0
|
||||||
0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i=0; ids[i]; ++i)
|
for (int i=0; ids[i]; ++i)
|
||||||
{
|
{
|
||||||
if (ids[i]==id)
|
if (ids[i]==id)
|
||||||
mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value);
|
{
|
||||||
|
mPlayerAttributes[static_cast<ESM::Attribute::AttributeID>(i)] = value;
|
||||||
|
if (mReviewDialog)
|
||||||
|
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID>(i), value);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,6 +156,7 @@ namespace MWGui
|
||||||
|
|
||||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
|
mPlayerSkillValues[parSkill] = value;
|
||||||
if (mReviewDialog)
|
if (mReviewDialog)
|
||||||
mReviewDialog->setSkillValue(parSkill, value);
|
mReviewDialog->setSkillValue(parSkill, value);
|
||||||
}
|
}
|
||||||
|
@ -155,6 +165,9 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (mReviewDialog)
|
if (mReviewDialog)
|
||||||
mReviewDialog->configureSkills(major, minor);
|
mReviewDialog->configureSkills(major, minor);
|
||||||
|
|
||||||
|
mPlayerMajorSkills = major;
|
||||||
|
mPlayerMinorSkills = minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::onFrame(float duration)
|
void CharacterCreation::onFrame(float duration)
|
||||||
|
@ -269,31 +282,21 @@ namespace MWGui
|
||||||
mReviewDialog->setClass(*playerClass);
|
mReviewDialog->setClass(*playerClass);
|
||||||
mReviewDialog->setBirthSign(player.getBirthSign());
|
mReviewDialog->setBirthSign(player.getBirthSign());
|
||||||
|
|
||||||
{
|
|
||||||
MWWorld::Ptr playerPtr = MWMechanics::getPlayer();
|
MWWorld::Ptr playerPtr = MWMechanics::getPlayer();
|
||||||
const MWMechanics::CreatureStats& stats = playerPtr.getClass().getCreatureStats(playerPtr);
|
const MWMechanics::CreatureStats& stats = playerPtr.getClass().getCreatureStats(playerPtr);
|
||||||
|
|
||||||
mReviewDialog->setHealth ( stats.getHealth() );
|
mReviewDialog->setHealth(stats.getHealth());
|
||||||
mReviewDialog->setMagicka( stats.getMagicka() );
|
mReviewDialog->setMagicka(stats.getMagicka());
|
||||||
mReviewDialog->setFatigue( stats.getFatigue() );
|
mReviewDialog->setFatigue(stats.getFatigue());
|
||||||
}
|
for (auto& attributePair : mPlayerAttributes)
|
||||||
|
|
||||||
{
|
|
||||||
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
|
||||||
for (auto& attributePair : attributes)
|
|
||||||
{
|
{
|
||||||
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (attributePair.first), attributePair.second);
|
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (attributePair.first), attributePair.second);
|
||||||
}
|
}
|
||||||
}
|
for (auto& skillPair : mPlayerSkillValues)
|
||||||
|
|
||||||
{
|
|
||||||
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
|
||||||
for (auto& skillPair : skills)
|
|
||||||
{
|
{
|
||||||
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (skillPair.first), skillPair.second);
|
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (skillPair.first), skillPair.second);
|
||||||
}
|
}
|
||||||
mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills());
|
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills);
|
||||||
}
|
|
||||||
|
|
||||||
mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
|
mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
|
||||||
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
#include <components/esm/loadclas.hpp>
|
#include <components/esm/loadclas.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../mwmechanics/stat.hpp"
|
#include "../mwmechanics/stat.hpp"
|
||||||
|
@ -56,6 +57,10 @@ namespace MWGui
|
||||||
osg::Group* mParent;
|
osg::Group* mParent;
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
||||||
|
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||||
|
std::map<int, MWMechanics::AttributeValue> mPlayerAttributes;
|
||||||
|
std::map<int, MWMechanics::SkillValue> mPlayerSkillValues;
|
||||||
|
|
||||||
//Dialogs
|
//Dialogs
|
||||||
TextInputDialog* mNameDialog;
|
TextInputDialog* mNameDialog;
|
||||||
RaceDialog* mRaceDialog;
|
RaceDialog* mRaceDialog;
|
||||||
|
|
36
apps/openmw/mwgui/textcolours.cpp
Normal file
36
apps/openmw/mwgui/textcolours.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include "textcolours.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_LanguageManager.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
MyGUI::Colour getTextColour(const std::string& type)
|
||||||
|
{
|
||||||
|
return MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=" + type + "}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextColours::loadColours()
|
||||||
|
{
|
||||||
|
header = getTextColour("header");
|
||||||
|
normal = getTextColour("normal");
|
||||||
|
notify = getTextColour("notify");
|
||||||
|
|
||||||
|
link = getTextColour("link");
|
||||||
|
linkOver = getTextColour("link_over");
|
||||||
|
linkPressed = getTextColour("link_pressed");
|
||||||
|
|
||||||
|
answer = getTextColour("answer");
|
||||||
|
answerOver = getTextColour("answer_over");
|
||||||
|
answerPressed = getTextColour("answer_pressed");
|
||||||
|
|
||||||
|
journalLink = getTextColour("journal_link");
|
||||||
|
journalLinkOver = getTextColour("journal_link_over");
|
||||||
|
journalLinkPressed = getTextColour("journal_link_pressed");
|
||||||
|
|
||||||
|
journalTopic = getTextColour("journal_topic");
|
||||||
|
journalTopicOver = getTextColour("journal_topic_over");
|
||||||
|
journalTopicPressed = getTextColour("journal_topic_pressed");
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,14 +5,12 @@
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
struct TextColours
|
struct TextColours
|
||||||
{
|
{
|
||||||
MyGUI::Colour header;
|
MyGUI::Colour header;
|
||||||
MyGUI::Colour normal;
|
MyGUI::Colour normal;
|
||||||
MyGUI::Colour notify;
|
MyGUI::Colour notify;
|
||||||
|
|
||||||
|
|
||||||
MyGUI::Colour link;
|
MyGUI::Colour link;
|
||||||
MyGUI::Colour linkOver;
|
MyGUI::Colour linkOver;
|
||||||
MyGUI::Colour linkPressed;
|
MyGUI::Colour linkPressed;
|
||||||
|
@ -28,6 +26,9 @@ namespace MWGui
|
||||||
MyGUI::Colour journalTopic;
|
MyGUI::Colour journalTopic;
|
||||||
MyGUI::Colour journalTopicOver;
|
MyGUI::Colour journalTopicOver;
|
||||||
MyGUI::Colour journalTopicPressed;
|
MyGUI::Colour journalTopicPressed;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void loadColours();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,6 +443,9 @@ namespace MWGui
|
||||||
// constant effects have no duration and no target
|
// constant effects have no duration and no target
|
||||||
if (!mEffectParams.mIsConstant)
|
if (!mEffectParams.mIsConstant)
|
||||||
{
|
{
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::AppliedOnce))
|
||||||
|
mEffectParams.mDuration = std::max(1, mEffectParams.mDuration);
|
||||||
|
|
||||||
if (mEffectParams.mDuration > 0 && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
if (mEffectParams.mDuration > 0 && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||||
{
|
{
|
||||||
spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfor", "") + " " + MyGUI::utility::toString(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs);
|
spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfor", "") + " " + MyGUI::utility::toString(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs);
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include <MyGUI_ClipboardManager.h>
|
#include <MyGUI_ClipboardManager.h>
|
||||||
#include <MyGUI_WidgetManager.h>
|
#include <MyGUI_WidgetManager.h>
|
||||||
|
|
||||||
|
// For BT_NO_PROFILE
|
||||||
|
#include <LinearMath/btQuickprof.h>
|
||||||
|
|
||||||
#include <SDL_keyboard.h>
|
#include <SDL_keyboard.h>
|
||||||
#include <SDL_clipboard.h>
|
#include <SDL_clipboard.h>
|
||||||
|
|
||||||
|
@ -126,19 +129,8 @@
|
||||||
#include "keyboardnavigation.hpp"
|
#include "keyboardnavigation.hpp"
|
||||||
#include "resourceskin.hpp"
|
#include "resourceskin.hpp"
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
MyGUI::Colour getTextColour(const std::string& type)
|
|
||||||
{
|
|
||||||
return MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=" + type + "}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
WindowManager::WindowManager(
|
WindowManager::WindowManager(
|
||||||
SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||||
const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||||
|
@ -191,12 +183,6 @@ namespace MWGui
|
||||||
, mCursorVisible(true)
|
, mCursorVisible(true)
|
||||||
, mCursorActive(false)
|
, mCursorActive(false)
|
||||||
, mPlayerBounty(-1)
|
, mPlayerBounty(-1)
|
||||||
, mPlayerName()
|
|
||||||
, mPlayerRaceId()
|
|
||||||
, mPlayerAttributes()
|
|
||||||
, mPlayerMajorSkills()
|
|
||||||
, mPlayerMinorSkills()
|
|
||||||
, mPlayerSkillValues()
|
|
||||||
, mGui(nullptr)
|
, mGui(nullptr)
|
||||||
, mGuiModes()
|
, mGuiModes()
|
||||||
, mCursorManager(nullptr)
|
, mCursorManager(nullptr)
|
||||||
|
@ -207,7 +193,6 @@ namespace MWGui
|
||||||
, mRestAllowed(true)
|
, mRestAllowed(true)
|
||||||
, mShowOwned(0)
|
, mShowOwned(0)
|
||||||
, mEncoding(encoding)
|
, mEncoding(encoding)
|
||||||
, mFontHeight(16)
|
|
||||||
, mVersionDescription(versionDescription)
|
, mVersionDescription(versionDescription)
|
||||||
, mWindowVisible(true)
|
, mWindowVisible(true)
|
||||||
{
|
{
|
||||||
|
@ -245,13 +230,6 @@ namespace MWGui
|
||||||
SpellView::registerComponents();
|
SpellView::registerComponents();
|
||||||
Gui::registerAllWidgets();
|
Gui::registerAllWidgets();
|
||||||
|
|
||||||
int fontSize = Settings::Manager::getInt("font size", "GUI");
|
|
||||||
fontSize = std::min(std::max(12, fontSize), 20);
|
|
||||||
mFontHeight = fontSize;
|
|
||||||
|
|
||||||
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
|
|
||||||
MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = newDelegate(this, &WindowManager::loadFontDelegate);
|
|
||||||
|
|
||||||
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
|
||||||
|
|
||||||
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
|
||||||
|
@ -308,94 +286,6 @@ namespace MWGui
|
||||||
Settings::Manager::getFloat("contrast", "Video"));
|
Settings::Manager::getFloat("contrast", "Video"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::loadFontDelegate(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version)
|
|
||||||
{
|
|
||||||
MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator();
|
|
||||||
bool createCopy = false;
|
|
||||||
while (resourceNode.next("Resource"))
|
|
||||||
{
|
|
||||||
std::string type, name;
|
|
||||||
resourceNode->findAttribute("type", type);
|
|
||||||
resourceNode->findAttribute("name", name);
|
|
||||||
|
|
||||||
if (name.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
|
|
||||||
{
|
|
||||||
createCopy = true;
|
|
||||||
|
|
||||||
// For TrueType fonts we should override Size and Resolution properties
|
|
||||||
// to allow to configure font size via config file, without need to edit XML files.
|
|
||||||
// Also we should take UI scaling factor in account.
|
|
||||||
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
|
|
||||||
resolution = std::min(960, std::max(48, resolution));
|
|
||||||
|
|
||||||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
|
||||||
resolution *= uiScale;
|
|
||||||
|
|
||||||
MyGUI::xml::ElementPtr resolutionNode = resourceNode->createChild("Property");
|
|
||||||
resolutionNode->addAttribute("key", "Resolution");
|
|
||||||
resolutionNode->addAttribute("value", std::to_string(resolution));
|
|
||||||
|
|
||||||
MyGUI::xml::ElementPtr sizeNode = resourceNode->createChild("Property");
|
|
||||||
sizeNode->addAttribute("key", "Size");
|
|
||||||
sizeNode->addAttribute("value", std::to_string(mFontHeight));
|
|
||||||
}
|
|
||||||
else if (Misc::StringUtils::ciEqual(type, "ResourceSkin") ||
|
|
||||||
Misc::StringUtils::ciEqual(type, "AutoSizedResourceSkin"))
|
|
||||||
{
|
|
||||||
// We should adjust line height for MyGUI widgets depending on font size
|
|
||||||
MyGUI::xml::ElementPtr heightNode = resourceNode->createChild("Property");
|
|
||||||
heightNode->addAttribute("key", "HeightLine");
|
|
||||||
heightNode->addAttribute("value", std::to_string(mFontHeight+2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MyGUI::ResourceManager::getInstance().loadFromXmlNode(_node, _file, _version);
|
|
||||||
|
|
||||||
if (createCopy)
|
|
||||||
{
|
|
||||||
MyGUI::xml::ElementPtr copy = _node->createCopy();
|
|
||||||
|
|
||||||
MyGUI::xml::ElementEnumerator copyFont = copy->getElementEnumerator();
|
|
||||||
while (copyFont.next("Resource"))
|
|
||||||
{
|
|
||||||
std::string type, name;
|
|
||||||
copyFont->findAttribute("type", type);
|
|
||||||
copyFont->findAttribute("name", name);
|
|
||||||
|
|
||||||
if (name.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
|
|
||||||
{
|
|
||||||
// Since the journal and books use the custom scaling factor depending on resolution,
|
|
||||||
// setup separate fonts with different Resolution to fit these windows.
|
|
||||||
// These fonts have an internal prefix.
|
|
||||||
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
|
|
||||||
resolution = std::min(960, std::max(48, resolution));
|
|
||||||
|
|
||||||
float currentX = Settings::Manager::getInt("resolution x", "Video");
|
|
||||||
float currentY = Settings::Manager::getInt("resolution y", "Video");
|
|
||||||
// TODO: read size from openmw_layout.xml
|
|
||||||
float heightScale = (currentY / 520);
|
|
||||||
float widthScale = (currentX / 600);
|
|
||||||
float uiScale = std::min(widthScale, heightScale);
|
|
||||||
resolution *= uiScale;
|
|
||||||
|
|
||||||
MyGUI::xml::ElementPtr resolutionNode = copyFont->createChild("Property");
|
|
||||||
resolutionNode->addAttribute("key", "Resolution");
|
|
||||||
resolutionNode->addAttribute("value", std::to_string(resolution));
|
|
||||||
|
|
||||||
copyFont->setAttribute("name", "Journalbook " + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MyGUI::ResourceManager::getInstance().loadFromXmlNode(copy, _file, _version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::loadUserFonts()
|
void WindowManager::loadUserFonts()
|
||||||
{
|
{
|
||||||
mFontLoader->loadTrueTypeFonts();
|
mFontLoader->loadTrueTypeFonts();
|
||||||
|
@ -407,26 +297,7 @@ namespace MWGui
|
||||||
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
|
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
|
||||||
int h = MyGUI::RenderManager::getInstance().getViewSize().height;
|
int h = MyGUI::RenderManager::getInstance().getViewSize().height;
|
||||||
|
|
||||||
mTextColours.header = getTextColour("header");
|
mTextColours.loadColours();
|
||||||
mTextColours.normal = getTextColour("normal");
|
|
||||||
mTextColours.notify = getTextColour("notify");
|
|
||||||
|
|
||||||
mTextColours.link = getTextColour("link");
|
|
||||||
mTextColours.linkOver = getTextColour("link_over");
|
|
||||||
mTextColours.linkPressed = getTextColour("link_pressed");
|
|
||||||
|
|
||||||
mTextColours.answer = getTextColour("answer");
|
|
||||||
mTextColours.answerOver = getTextColour("answer_over");
|
|
||||||
mTextColours.answerPressed = getTextColour("answer_pressed");
|
|
||||||
|
|
||||||
mTextColours.journalLink = getTextColour("journal_link");
|
|
||||||
mTextColours.journalLinkOver = getTextColour("journal_link_over");
|
|
||||||
mTextColours.journalLinkPressed = getTextColour("journal_link_pressed");
|
|
||||||
|
|
||||||
mTextColours.journalTopic = getTextColour("journal_topic");
|
|
||||||
mTextColours.journalTopicOver = getTextColour("journal_topic_over");
|
|
||||||
mTextColours.journalTopicPressed = getTextColour("journal_topic_pressed");
|
|
||||||
|
|
||||||
|
|
||||||
mDragAndDrop = new DragAndDrop();
|
mDragAndDrop = new DragAndDrop();
|
||||||
|
|
||||||
|
@ -612,17 +483,6 @@ namespace MWGui
|
||||||
|
|
||||||
mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem);
|
mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem);
|
||||||
|
|
||||||
// Setup player stats
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
|
||||||
{
|
|
||||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
|
||||||
{
|
|
||||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePinnedWindows();
|
updatePinnedWindows();
|
||||||
|
|
||||||
// Set up visibility
|
// Set up visibility
|
||||||
|
@ -631,7 +491,7 @@ namespace MWGui
|
||||||
|
|
||||||
int WindowManager::getFontHeight() const
|
int WindowManager::getFontHeight() const
|
||||||
{
|
{
|
||||||
return mFontHeight;
|
return mFontLoader->getFontHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setNewGame(bool newgame)
|
void WindowManager::setNewGame(bool newgame)
|
||||||
|
@ -652,7 +512,6 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mKeyboardNavigation.reset();
|
mKeyboardNavigation.reset();
|
||||||
|
|
||||||
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
|
|
||||||
MyGUI::LanguageManager::getInstance().eventRequestTag.clear();
|
MyGUI::LanguageManager::getInstance().eventRequestTag.clear();
|
||||||
MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear();
|
MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear();
|
||||||
MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear();
|
MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear();
|
||||||
|
@ -824,32 +683,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mStatsWindow->setValue (id, value);
|
mStatsWindow->setValue (id, value);
|
||||||
mCharGen->setValue(id, value);
|
mCharGen->setValue(id, value);
|
||||||
|
|
||||||
static const char *ids[] =
|
|
||||||
{
|
|
||||||
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
|
|
||||||
"AttribVal6", "AttribVal7", "AttribVal8"
|
|
||||||
};
|
|
||||||
static ESM::Attribute::AttributeID attributes[] =
|
|
||||||
{
|
|
||||||
ESM::Attribute::Strength,
|
|
||||||
ESM::Attribute::Intelligence,
|
|
||||||
ESM::Attribute::Willpower,
|
|
||||||
ESM::Attribute::Agility,
|
|
||||||
ESM::Attribute::Speed,
|
|
||||||
ESM::Attribute::Endurance,
|
|
||||||
ESM::Attribute::Personality,
|
|
||||||
ESM::Attribute::Luck
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < sizeof(ids)/sizeof(ids[0]); ++i)
|
|
||||||
{
|
|
||||||
if (id != ids[i])
|
|
||||||
continue;
|
|
||||||
mPlayerAttributes[attributes[i]] = value;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value)
|
void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
|
@ -857,7 +691,6 @@ namespace MWGui
|
||||||
/// allow custom skills.
|
/// allow custom skills.
|
||||||
mStatsWindow->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
|
mStatsWindow->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
|
||||||
mCharGen->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
|
mCharGen->setValue(static_cast<ESM::Skill::SkillEnum> (parSkill), value);
|
||||||
mPlayerSkillValues[parSkill] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
|
||||||
|
@ -870,10 +703,6 @@ namespace MWGui
|
||||||
void WindowManager::setValue (const std::string& id, const std::string& value)
|
void WindowManager::setValue (const std::string& id, const std::string& value)
|
||||||
{
|
{
|
||||||
mStatsWindow->setValue (id, value);
|
mStatsWindow->setValue (id, value);
|
||||||
if (id=="name")
|
|
||||||
mPlayerName = value;
|
|
||||||
else if (id=="race")
|
|
||||||
mPlayerRaceId = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setValue (const std::string& id, int value)
|
void WindowManager::setValue (const std::string& id, int value)
|
||||||
|
@ -895,8 +724,6 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mStatsWindow->configureSkills (major, minor);
|
mStatsWindow->configureSkills (major, minor);
|
||||||
mCharGen->configureSkills(major, minor);
|
mCharGen->configureSkills(major, minor);
|
||||||
mPlayerMajorSkills = major;
|
|
||||||
mPlayerMinorSkills = minor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::updateSkillArea()
|
void WindowManager::updateSkillArea()
|
||||||
|
@ -1045,7 +872,7 @@ namespace MWGui
|
||||||
mHud->setPlayerPos(x, y, u, v);
|
mHud->setPlayerPos(x, y, u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::onFrame (float frameDuration)
|
void WindowManager::update (float frameDuration)
|
||||||
{
|
{
|
||||||
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
|
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
|
||||||
MWBase::StateManager::State_NoGame;
|
MWBase::StateManager::State_NoGame;
|
||||||
|
@ -1731,26 +1558,6 @@ namespace MWGui
|
||||||
return mGuiModes.back();
|
return mGuiModes.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, MWMechanics::SkillValue > WindowManager::getPlayerSkillValues()
|
|
||||||
{
|
|
||||||
return mPlayerSkillValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<int, MWMechanics::AttributeValue > WindowManager::getPlayerAttributeValues()
|
|
||||||
{
|
|
||||||
return mPlayerAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowManager::SkillList WindowManager::getPlayerMinorSkills()
|
|
||||||
{
|
|
||||||
return mPlayerMinorSkills;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowManager::SkillList WindowManager::getPlayerMajorSkills()
|
|
||||||
{
|
|
||||||
return mPlayerMajorSkills;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::disallowMouse()
|
void WindowManager::disallowMouse()
|
||||||
{
|
{
|
||||||
mInputBlocker->setVisible (true);
|
mInputBlocker->setVisible (true);
|
||||||
|
@ -2331,7 +2138,9 @@ namespace MWGui
|
||||||
|
|
||||||
void WindowManager::toggleDebugWindow()
|
void WindowManager::toggleDebugWindow()
|
||||||
{
|
{
|
||||||
|
#ifndef BT_NO_PROFILE
|
||||||
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::cycleSpell(bool next)
|
void WindowManager::cycleSpell(bool next)
|
||||||
|
|
|
@ -356,13 +356,7 @@ namespace MWGui
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual void onFrame (float frameDuration);
|
virtual void update (float duration);
|
||||||
|
|
||||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
|
||||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues();
|
|
||||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues();
|
|
||||||
virtual SkillList getPlayerMinorSkills();
|
|
||||||
virtual SkillList getPlayerMajorSkills();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches a GMST string from the store, if there is no setting with the given
|
* Fetches a GMST string from the store, if there is no setting with the given
|
||||||
|
@ -503,8 +497,6 @@ namespace MWGui
|
||||||
MWWorld::Ptr mSelectedEnchantItem;
|
MWWorld::Ptr mSelectedEnchantItem;
|
||||||
MWWorld::Ptr mSelectedWeapon;
|
MWWorld::Ptr mSelectedWeapon;
|
||||||
|
|
||||||
void loadFontDelegate(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version);
|
|
||||||
|
|
||||||
std::vector<WindowModal*> mCurrentModals;
|
std::vector<WindowModal*> mCurrentModals;
|
||||||
|
|
||||||
// Markers placed manually by the player. Must be shared between both map views (the HUD map and the map window).
|
// Markers placed manually by the player. Must be shared between both map views (the HUD map and the map window).
|
||||||
|
@ -571,14 +563,6 @@ namespace MWGui
|
||||||
|
|
||||||
void setCursorVisible(bool visible);
|
void setCursorVisible(bool visible);
|
||||||
|
|
||||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
|
||||||
// Various stats about player as needed by window manager
|
|
||||||
std::string mPlayerName;
|
|
||||||
std::string mPlayerRaceId;
|
|
||||||
std::map<int, MWMechanics::AttributeValue > mPlayerAttributes;
|
|
||||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
|
||||||
std::map<int, MWMechanics::SkillValue > mPlayerSkillValues;
|
|
||||||
|
|
||||||
MyGUI::Gui *mGui; // Gui
|
MyGUI::Gui *mGui; // Gui
|
||||||
|
|
||||||
struct GuiModeState
|
struct GuiModeState
|
||||||
|
@ -628,8 +612,6 @@ namespace MWGui
|
||||||
|
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
|
|
||||||
int mFontHeight;
|
|
||||||
|
|
||||||
std::string mVersionDescription;
|
std::string mVersionDescription;
|
||||||
|
|
||||||
bool mWindowVisible;
|
bool mWindowVisible;
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace MWInput
|
||||||
, mSneakToggleShortcutTimer(0.f)
|
, mSneakToggleShortcutTimer(0.f)
|
||||||
, mGamepadZoom(0)
|
, mGamepadZoom(0)
|
||||||
, mGamepadGuiCursorEnabled(true)
|
, mGamepadGuiCursorEnabled(true)
|
||||||
, mControlsDisabled(false)
|
|
||||||
, mJoystickLastUsed(false)
|
, mJoystickLastUsed(false)
|
||||||
, mSneakGamepadShortcut(false)
|
, mSneakGamepadShortcut(false)
|
||||||
, mGamepadPreviewMode(false)
|
, mGamepadPreviewMode(false)
|
||||||
|
@ -83,9 +82,8 @@ namespace MWInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControllerManager::update(float dt, bool disableControls)
|
bool ControllerManager::update(float dt)
|
||||||
{
|
{
|
||||||
mControlsDisabled = disableControls;
|
|
||||||
mGamepadPreviewMode = mActionManager->getPreviewDelay() == 1.f;
|
mGamepadPreviewMode = mActionManager->getPreviewDelay() == 1.f;
|
||||||
|
|
||||||
if (mGuiCursorEnabled && !(mJoystickLastUsed && !mGamepadGuiCursorEnabled))
|
if (mGuiCursorEnabled && !(mJoystickLastUsed && !mGamepadGuiCursorEnabled))
|
||||||
|
@ -232,7 +230,7 @@ namespace MWInput
|
||||||
auto kc = sdlKeyToMyGUI(SDLK_ESCAPE);
|
auto kc = sdlKeyToMyGUI(SDLK_ESCAPE);
|
||||||
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyPress(kc, 0));
|
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyPress(kc, 0));
|
||||||
|
|
||||||
if (!mControlsDisabled)
|
if (!MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
mBindingsManager->controllerButtonPressed(deviceID, arg);
|
mBindingsManager->controllerButtonPressed(deviceID, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +242,7 @@ namespace MWInput
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mJoystickEnabled || mControlsDisabled)
|
if (!mJoystickEnabled || MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mJoystickLastUsed = true;
|
mJoystickLastUsed = true;
|
||||||
|
@ -275,7 +273,7 @@ namespace MWInput
|
||||||
|
|
||||||
void ControllerManager::axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg)
|
void ControllerManager::axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg)
|
||||||
{
|
{
|
||||||
if (!mJoystickEnabled || mControlsDisabled)
|
if (!mJoystickEnabled || MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mJoystickLastUsed = true;
|
mJoystickLastUsed = true;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace MWInput
|
||||||
|
|
||||||
virtual ~ControllerManager() = default;
|
virtual ~ControllerManager() = default;
|
||||||
|
|
||||||
bool update(float dt, bool disableControls);
|
bool update(float dt);
|
||||||
|
|
||||||
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
|
@ -56,7 +56,6 @@ namespace MWInput
|
||||||
float mSneakToggleShortcutTimer;
|
float mSneakToggleShortcutTimer;
|
||||||
float mGamepadZoom;
|
float mGamepadZoom;
|
||||||
bool mGamepadGuiCursorEnabled;
|
bool mGamepadGuiCursorEnabled;
|
||||||
bool mControlsDisabled;
|
|
||||||
bool mJoystickLastUsed;
|
bool mJoystickLastUsed;
|
||||||
bool mGuiCursorEnabled;
|
bool mGuiCursorEnabled;
|
||||||
bool mSneakGamepadShortcut;
|
bool mSneakGamepadShortcut;
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace MWInput
|
||||||
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
|
||||||
const std::string& userFile, bool userFileExists, const std::string& userControllerBindingsFile,
|
const std::string& userFile, bool userFileExists, const std::string& userControllerBindingsFile,
|
||||||
const std::string& controllerBindingsFile, bool grab)
|
const std::string& controllerBindingsFile, bool grab)
|
||||||
: mGrabCursor(Settings::Manager::getBool("grab cursor", "Input"))
|
: mControlsDisabled(false)
|
||||||
{
|
{
|
||||||
mInputWrapper = new SDLUtil::InputWrapper(window, viewer, grab);
|
mInputWrapper = new SDLUtil::InputWrapper(window, viewer, grab);
|
||||||
mInputWrapper->setWindowEventCallback(MWBase::Environment::get().getWindowManager());
|
mInputWrapper->setWindowEventCallback(MWBase::Environment::get().getWindowManager());
|
||||||
|
@ -81,47 +81,25 @@ namespace MWInput
|
||||||
mActionManager->setAttemptJump(jumping);
|
mActionManager->setAttemptJump(jumping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::updateCursorMode()
|
|
||||||
{
|
|
||||||
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
|
|
||||||
&& !MWBase::Environment::get().getWindowManager()->isConsoleMode();
|
|
||||||
|
|
||||||
bool wasRelative = mInputWrapper->getMouseRelative();
|
|
||||||
bool isRelative = !MWBase::Environment::get().getWindowManager()->isGuiMode();
|
|
||||||
|
|
||||||
// don't keep the pointer away from the window edge in gui mode
|
|
||||||
// stop using raw mouse motions and switch to system cursor movements
|
|
||||||
mInputWrapper->setMouseRelative(isRelative);
|
|
||||||
|
|
||||||
//we let the mouse escape in the main menu
|
|
||||||
mInputWrapper->setGrabPointer(grab && (mGrabCursor || isRelative));
|
|
||||||
|
|
||||||
//we switched to non-relative mode, move our cursor to where the in-game
|
|
||||||
//cursor is
|
|
||||||
if (!isRelative && wasRelative != isRelative)
|
|
||||||
{
|
|
||||||
mMouseManager->warpMouse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::update(float dt, bool disableControls, bool disableEvents)
|
void InputManager::update(float dt, bool disableControls, bool disableEvents)
|
||||||
{
|
{
|
||||||
|
mControlsDisabled = disableControls;
|
||||||
|
|
||||||
mInputWrapper->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
|
mInputWrapper->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
|
||||||
mInputWrapper->capture(disableEvents);
|
mInputWrapper->capture(disableEvents);
|
||||||
|
|
||||||
mKeyboardManager->setControlsDisabled(disableControls);
|
|
||||||
if (disableControls)
|
if (disableControls)
|
||||||
{
|
{
|
||||||
updateCursorMode();
|
mMouseManager->updateCursorMode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mBindingsManager->update(dt);
|
mBindingsManager->update(dt);
|
||||||
|
|
||||||
updateCursorMode();
|
mMouseManager->updateCursorMode();
|
||||||
|
|
||||||
bool controllerMove = mControllerManager->update(dt, disableControls);
|
bool controllerMove = mControllerManager->update(dt);
|
||||||
mMouseManager->update(dt, disableControls);
|
mMouseManager->update(dt);
|
||||||
mSensorManager->update(dt);
|
mSensorManager->update(dt);
|
||||||
mActionManager->update(dt, controllerMove);
|
mActionManager->update(dt, controllerMove);
|
||||||
}
|
}
|
||||||
|
@ -152,12 +130,6 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
void InputManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
{
|
{
|
||||||
for (const auto& setting : changed)
|
|
||||||
{
|
|
||||||
if (setting.first == "Input" && setting.second == "grab cursor")
|
|
||||||
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
|
||||||
}
|
|
||||||
|
|
||||||
mMouseManager->processChangedSettings(changed);
|
mMouseManager->processChangedSettings(changed);
|
||||||
mSensorManager->processChangedSettings(changed);
|
mSensorManager->processChangedSettings(changed);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,13 @@ namespace MWInput
|
||||||
|
|
||||||
virtual void executeAction(int action);
|
virtual void executeAction(int action);
|
||||||
|
|
||||||
|
virtual bool controlsDisabled() { return mControlsDisabled; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void convertMousePosForMyGUI(int& x, int& y);
|
void convertMousePosForMyGUI(int& x, int& y);
|
||||||
|
|
||||||
void handleGuiArrowKey(int action);
|
void handleGuiArrowKey(int action);
|
||||||
|
|
||||||
void updateCursorMode();
|
|
||||||
|
|
||||||
void quickKey(int index);
|
void quickKey(int index);
|
||||||
void showQuickKeysMenu();
|
void showQuickKeysMenu();
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ namespace MWInput
|
||||||
|
|
||||||
SDLUtil::InputWrapper* mInputWrapper;
|
SDLUtil::InputWrapper* mInputWrapper;
|
||||||
|
|
||||||
bool mGrabCursor;
|
bool mControlsDisabled;
|
||||||
|
|
||||||
ControlSwitch* mControlSwitch;
|
ControlSwitch* mControlSwitch;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
KeyboardManager::KeyboardManager(BindingsManager* bindingsManager)
|
KeyboardManager::KeyboardManager(BindingsManager* bindingsManager)
|
||||||
: mBindingsManager(bindingsManager)
|
: mBindingsManager(bindingsManager)
|
||||||
, mControlsDisabled(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +52,11 @@ namespace MWInput
|
||||||
if (arg.repeat)
|
if (arg.repeat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!mControlsDisabled && !consumed)
|
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
|
||||||
|
if (!input->controlsDisabled() && !consumed)
|
||||||
mBindingsManager->keyPressed(arg);
|
mBindingsManager->keyPressed(arg);
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->setJoystickLastUsed(false);
|
input->setJoystickLastUsed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardManager::keyReleased(const SDL_KeyboardEvent &arg)
|
void KeyboardManager::keyReleased(const SDL_KeyboardEvent &arg)
|
||||||
|
|
|
@ -19,12 +19,8 @@ namespace MWInput
|
||||||
virtual void keyPressed(const SDL_KeyboardEvent &arg);
|
virtual void keyPressed(const SDL_KeyboardEvent &arg);
|
||||||
virtual void keyReleased(const SDL_KeyboardEvent &arg);
|
virtual void keyReleased(const SDL_KeyboardEvent &arg);
|
||||||
|
|
||||||
void setControlsDisabled(bool disabled) { mControlsDisabled = disabled; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BindingsManager* mBindingsManager;
|
BindingsManager* mBindingsManager;
|
||||||
|
|
||||||
bool mControlsDisabled;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,8 +24,9 @@ namespace MWInput
|
||||||
MouseManager::MouseManager(BindingsManager* bindingsManager, SDLUtil::InputWrapper* inputWrapper, SDL_Window* window)
|
MouseManager::MouseManager(BindingsManager* bindingsManager, SDLUtil::InputWrapper* inputWrapper, SDL_Window* window)
|
||||||
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
||||||
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
||||||
, mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input"))
|
, mGrabCursor(Settings::Manager::getBool("grab cursor", "Input"))
|
||||||
, mCameraYMultiplier (Settings::Manager::getFloat("camera y multiplier", "Input"))
|
, mCameraSensitivity(Settings::Manager::getFloat("camera sensitivity", "Input"))
|
||||||
|
, mCameraYMultiplier(Settings::Manager::getFloat("camera y multiplier", "Input"))
|
||||||
, mBindingsManager(bindingsManager)
|
, mBindingsManager(bindingsManager)
|
||||||
, mInputWrapper(inputWrapper)
|
, mInputWrapper(inputWrapper)
|
||||||
, mInvUiScalingFactor(1.f)
|
, mInvUiScalingFactor(1.f)
|
||||||
|
@ -33,7 +34,6 @@ namespace MWInput
|
||||||
, mGuiCursorY(0)
|
, mGuiCursorY(0)
|
||||||
, mMouseWheel(0)
|
, mMouseWheel(0)
|
||||||
, mMouseLookEnabled(false)
|
, mMouseLookEnabled(false)
|
||||||
, mControlsDisabled(false)
|
|
||||||
, mGuiCursorEnabled(true)
|
, mGuiCursorEnabled(true)
|
||||||
{
|
{
|
||||||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
|
@ -59,6 +59,9 @@ namespace MWInput
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "camera sensitivity")
|
if (setting.first == "Input" && setting.second == "camera sensitivity")
|
||||||
mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input");
|
mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "grab cursor")
|
||||||
|
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +91,7 @@ namespace MWInput
|
||||||
MWBase::Environment::get().getWindowManager()->setCursorActive(true);
|
MWBase::Environment::get().getWindowManager()->setCursorActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMouseLookEnabled && !mControlsDisabled)
|
if (mMouseLookEnabled && !input->controlsDisabled())
|
||||||
{
|
{
|
||||||
float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
||||||
float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
||||||
|
@ -136,10 +139,11 @@ namespace MWInput
|
||||||
|
|
||||||
void MouseManager::mouseWheelMoved(const SDL_MouseWheelEvent &arg)
|
void MouseManager::mouseWheelMoved(const SDL_MouseWheelEvent &arg)
|
||||||
{
|
{
|
||||||
if (mBindingsManager->isDetectingBindingState() || !mControlsDisabled)
|
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
|
||||||
|
if (mBindingsManager->isDetectingBindingState() || !input->controlsDisabled())
|
||||||
mBindingsManager->mouseWheelMoved(arg);
|
mBindingsManager->mouseWheelMoved(arg);
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->setJoystickLastUsed(false);
|
input->setJoystickLastUsed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MouseManager::mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id)
|
void MouseManager::mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id)
|
||||||
|
@ -169,10 +173,31 @@ namespace MWInput
|
||||||
mBindingsManager->mousePressed(arg, id);
|
mBindingsManager->mousePressed(arg, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MouseManager::update(float dt, bool disableControls)
|
void MouseManager::updateCursorMode()
|
||||||
{
|
{
|
||||||
mControlsDisabled = disableControls;
|
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
|
||||||
|
&& !MWBase::Environment::get().getWindowManager()->isConsoleMode();
|
||||||
|
|
||||||
|
bool wasRelative = mInputWrapper->getMouseRelative();
|
||||||
|
bool isRelative = !MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
|
||||||
|
// don't keep the pointer away from the window edge in gui mode
|
||||||
|
// stop using raw mouse motions and switch to system cursor movements
|
||||||
|
mInputWrapper->setMouseRelative(isRelative);
|
||||||
|
|
||||||
|
//we let the mouse escape in the main menu
|
||||||
|
mInputWrapper->setGrabPointer(grab && (mGrabCursor || isRelative));
|
||||||
|
|
||||||
|
//we switched to non-relative mode, move our cursor to where the in-game
|
||||||
|
//cursor is
|
||||||
|
if (!isRelative && wasRelative != isRelative)
|
||||||
|
{
|
||||||
|
warpMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::update(float dt)
|
||||||
|
{
|
||||||
if (!mMouseLookEnabled)
|
if (!mMouseLookEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ namespace MWInput
|
||||||
|
|
||||||
virtual ~MouseManager() = default;
|
virtual ~MouseManager() = default;
|
||||||
|
|
||||||
void update(float dt, bool disableControls);
|
void updateCursorMode();
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
virtual void mouseMoved(const SDLUtil::MouseMotionEvent &arg);
|
virtual void mouseMoved(const SDLUtil::MouseMotionEvent &arg);
|
||||||
virtual void mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id);
|
virtual void mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id);
|
||||||
|
@ -40,6 +41,7 @@ namespace MWInput
|
||||||
private:
|
private:
|
||||||
bool mInvertX;
|
bool mInvertX;
|
||||||
bool mInvertY;
|
bool mInvertY;
|
||||||
|
bool mGrabCursor;
|
||||||
float mCameraSensitivity;
|
float mCameraSensitivity;
|
||||||
float mCameraYMultiplier;
|
float mCameraYMultiplier;
|
||||||
|
|
||||||
|
@ -51,7 +53,6 @@ namespace MWInput
|
||||||
float mGuiCursorY;
|
float mGuiCursorY;
|
||||||
int mMouseWheel;
|
int mMouseWheel;
|
||||||
bool mMouseLookEnabled;
|
bool mMouseLookEnabled;
|
||||||
bool mControlsDisabled;
|
|
||||||
bool mGuiCursorEnabled;
|
bool mGuiCursorEnabled;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,12 @@
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void ActiveSpells::update() const
|
void ActiveSpells::update(float duration) const
|
||||||
{
|
{
|
||||||
bool rebuild = false;
|
bool rebuild = false;
|
||||||
|
|
||||||
MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp();
|
|
||||||
|
|
||||||
// Erase no longer active spells and effects
|
// Erase no longer active spells and effects
|
||||||
if (mLastUpdate!=now)
|
if (duration > 0)
|
||||||
{
|
{
|
||||||
TContainer::iterator iter (mSpells.begin());
|
TContainer::iterator iter (mSpells.begin());
|
||||||
while (iter!=mSpells.end())
|
while (iter!=mSpells.end())
|
||||||
|
@ -34,21 +32,20 @@ namespace MWMechanics
|
||||||
std::vector<ActiveEffect>& effects = iter->second.mEffects;
|
std::vector<ActiveEffect>& effects = iter->second.mEffects;
|
||||||
for (std::vector<ActiveEffect>::iterator effectIt = effects.begin(); effectIt != effects.end();)
|
for (std::vector<ActiveEffect>::iterator effectIt = effects.begin(); effectIt != effects.end();)
|
||||||
{
|
{
|
||||||
MWWorld::TimeStamp start = iter->second.mTimeStamp;
|
if (effectIt->mTimeLeft <= 0)
|
||||||
MWWorld::TimeStamp end = start + static_cast<double>(effectIt->mDuration)*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
|
|
||||||
if (end <= now)
|
|
||||||
{
|
{
|
||||||
effectIt = effects.erase(effectIt);
|
effectIt = effects.erase(effectIt);
|
||||||
rebuild = true;
|
rebuild = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
effectIt->mTimeLeft -= duration;
|
||||||
++effectIt;
|
++effectIt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastUpdate = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSpellsChanged)
|
if (mSpellsChanged)
|
||||||
|
@ -63,24 +60,15 @@ namespace MWMechanics
|
||||||
|
|
||||||
void ActiveSpells::rebuildEffects() const
|
void ActiveSpells::rebuildEffects() const
|
||||||
{
|
{
|
||||||
MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp();
|
|
||||||
|
|
||||||
mEffects = MagicEffects();
|
mEffects = MagicEffects();
|
||||||
|
|
||||||
for (TIterator iter (begin()); iter!=end(); ++iter)
|
for (TIterator iter (begin()); iter!=end(); ++iter)
|
||||||
{
|
{
|
||||||
const MWWorld::TimeStamp& start = iter->second.mTimeStamp;
|
|
||||||
|
|
||||||
const std::vector<ActiveEffect>& effects = iter->second.mEffects;
|
const std::vector<ActiveEffect>& effects = iter->second.mEffects;
|
||||||
|
|
||||||
for (std::vector<ActiveEffect>::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt)
|
for (std::vector<ActiveEffect>::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt)
|
||||||
{
|
{
|
||||||
double duration = effectIt->mDuration;
|
if (effectIt->mTimeLeft > 0)
|
||||||
MWWorld::TimeStamp end = start;
|
|
||||||
end += duration *
|
|
||||||
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
|
|
||||||
|
|
||||||
if (end>now)
|
|
||||||
mEffects.add(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), MWMechanics::EffectParam(effectIt->mMagnitude));
|
mEffects.add(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), MWMechanics::EffectParam(effectIt->mMagnitude));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,12 +76,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
ActiveSpells::ActiveSpells()
|
ActiveSpells::ActiveSpells()
|
||||||
: mSpellsChanged (false)
|
: mSpellsChanged (false)
|
||||||
, mLastUpdate (MWBase::Environment::get().getWorld()->getTimeStamp())
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const MagicEffects& ActiveSpells::getMagicEffects() const
|
const MagicEffects& ActiveSpells::getMagicEffects() const
|
||||||
{
|
{
|
||||||
update();
|
update(0.f);
|
||||||
return mEffects;
|
return mEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,19 +103,14 @@ namespace MWMechanics
|
||||||
for (std::vector<ActiveEffect>::const_iterator iter (effects.begin());
|
for (std::vector<ActiveEffect>::const_iterator iter (effects.begin());
|
||||||
iter!=effects.end(); ++iter)
|
iter!=effects.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (iter->mDuration > duration)
|
if (iter->mTimeLeft > duration)
|
||||||
duration = iter->mDuration;
|
duration = iter->mTimeLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
double scaledDuration = duration *
|
if (duration < 0)
|
||||||
MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60);
|
|
||||||
|
|
||||||
double usedUp = MWBase::Environment::get().getWorld()->getTimeStamp() - iterator->second.mTimeStamp;
|
|
||||||
|
|
||||||
if (usedUp>=scaledDuration)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return scaledDuration-usedUp;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ActiveSpells::isSpellActive(const std::string& id) const
|
bool ActiveSpells::isSpellActive(const std::string& id) const
|
||||||
|
@ -152,7 +134,6 @@ namespace MWMechanics
|
||||||
TContainer::iterator it(mSpells.find(id));
|
TContainer::iterator it(mSpells.find(id));
|
||||||
|
|
||||||
ActiveSpellParams params;
|
ActiveSpellParams params;
|
||||||
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
|
||||||
params.mEffects = effects;
|
params.mEffects = effects;
|
||||||
params.mDisplayName = displayName;
|
params.mDisplayName = displayName;
|
||||||
params.mCasterActorId = casterActorId;
|
params.mCasterActorId = casterActorId;
|
||||||
|
@ -211,19 +192,15 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||||
{
|
{
|
||||||
float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
|
||||||
|
|
||||||
for (std::vector<ActiveEffect>::const_iterator effectIt = it->second.mEffects.begin();
|
for (std::vector<ActiveEffect>::const_iterator effectIt = it->second.mEffects.begin();
|
||||||
effectIt != it->second.mEffects.end(); ++effectIt)
|
effectIt != it->second.mEffects.end(); ++effectIt)
|
||||||
{
|
{
|
||||||
std::string name = it->second.mDisplayName;
|
std::string name = it->second.mDisplayName;
|
||||||
|
|
||||||
float remainingTime = effectIt->mDuration +
|
|
||||||
static_cast<float>(it->second.mTimeStamp - MWBase::Environment::get().getWorld()->getTimeStamp())*3600/timeScale;
|
|
||||||
float magnitude = effectIt->mMagnitude;
|
float magnitude = effectIt->mMagnitude;
|
||||||
|
|
||||||
if (magnitude)
|
if (magnitude)
|
||||||
visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->first, it->second.mCasterActorId, magnitude, remainingTime, effectIt->mDuration);
|
visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->first, it->second.mCasterActorId, magnitude, effectIt->mTimeLeft, effectIt->mDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +342,6 @@ namespace MWMechanics
|
||||||
params.mEffects = it->second.mEffects;
|
params.mEffects = it->second.mEffects;
|
||||||
params.mCasterActorId = it->second.mCasterActorId;
|
params.mCasterActorId = it->second.mCasterActorId;
|
||||||
params.mDisplayName = it->second.mDisplayName;
|
params.mDisplayName = it->second.mDisplayName;
|
||||||
params.mTimeStamp = it->second.mTimeStamp.toEsm();
|
|
||||||
|
|
||||||
state.mSpells.insert (std::make_pair(it->first, params));
|
state.mSpells.insert (std::make_pair(it->first, params));
|
||||||
}
|
}
|
||||||
|
@ -380,7 +356,6 @@ namespace MWMechanics
|
||||||
params.mEffects = it->second.mEffects;
|
params.mEffects = it->second.mEffects;
|
||||||
params.mCasterActorId = it->second.mCasterActorId;
|
params.mCasterActorId = it->second.mCasterActorId;
|
||||||
params.mDisplayName = it->second.mDisplayName;
|
params.mDisplayName = it->second.mDisplayName;
|
||||||
params.mTimeStamp = MWWorld::TimeStamp(it->second.mTimeStamp);
|
|
||||||
|
|
||||||
mSpells.insert (std::make_pair(it->first, params));
|
mSpells.insert (std::make_pair(it->first, params));
|
||||||
mSpellsChanged = true;
|
mSpellsChanged = true;
|
||||||
|
|
|
@ -44,14 +44,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
TIterator end() const;
|
TIterator end() const;
|
||||||
|
|
||||||
|
void update(float duration) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
mutable TContainer mSpells;
|
mutable TContainer mSpells;
|
||||||
mutable MagicEffects mEffects;
|
mutable MagicEffects mEffects;
|
||||||
mutable bool mSpellsChanged;
|
mutable bool mSpellsChanged;
|
||||||
mutable MWWorld::TimeStamp mLastUpdate;
|
|
||||||
|
|
||||||
void update() const;
|
|
||||||
|
|
||||||
void rebuildEffects() const;
|
void rebuildEffects() const;
|
||||||
|
|
||||||
|
|
|
@ -18,4 +18,44 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
return mCharacterController.get();
|
return mCharacterController.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Actor::getGreetingTimer() const
|
||||||
|
{
|
||||||
|
return mGreetingTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setGreetingTimer(int timer)
|
||||||
|
{
|
||||||
|
mGreetingTimer = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Actor::getAngleToPlayer() const
|
||||||
|
{
|
||||||
|
return mTargetAngleRadians;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setAngleToPlayer(float angle)
|
||||||
|
{
|
||||||
|
mTargetAngleRadians = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
GreetingState Actor::getGreetingState() const
|
||||||
|
{
|
||||||
|
return mGreetingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setGreetingState(GreetingState state)
|
||||||
|
{
|
||||||
|
mGreetingState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actor::isTurningToPlayer() const
|
||||||
|
{
|
||||||
|
return mIsTurningToPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setTurningToPlayer(bool turning)
|
||||||
|
{
|
||||||
|
mIsTurningToPlayer = turning;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
class Animation;
|
class Animation;
|
||||||
|
@ -27,8 +29,24 @@ namespace MWMechanics
|
||||||
|
|
||||||
CharacterController* getCharacterController();
|
CharacterController* getCharacterController();
|
||||||
|
|
||||||
|
int getGreetingTimer() const;
|
||||||
|
void setGreetingTimer(int timer);
|
||||||
|
|
||||||
|
float getAngleToPlayer() const;
|
||||||
|
void setAngleToPlayer(float angle);
|
||||||
|
|
||||||
|
GreetingState getGreetingState() const;
|
||||||
|
void setGreetingState(GreetingState state);
|
||||||
|
|
||||||
|
bool isTurningToPlayer() const;
|
||||||
|
void setTurningToPlayer(bool turning);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CharacterController> mCharacterController;
|
std::unique_ptr<CharacterController> mCharacterController;
|
||||||
|
int mGreetingTimer{0};
|
||||||
|
float mTargetAngleRadians{0.f};
|
||||||
|
GreetingState mGreetingState{Greet_None};
|
||||||
|
bool mIsTurningToPlayer{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,7 +480,7 @@ namespace MWMechanics
|
||||||
actor.getClass().getMovementSettings(actor).mSpeedFactor = newSpeedFactor;
|
actor.getClass().getMovementSettings(actor).mSpeedFactor = newSpeedFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::updateGreetingState(const MWWorld::Ptr& actor, bool turnOnly)
|
void Actors::updateGreetingState(const MWWorld::Ptr& actor, Actor& actorState, bool turnOnly)
|
||||||
{
|
{
|
||||||
if (!actor.getClass().isActor() || actor == getPlayer())
|
if (!actor.getClass().isActor() || actor == getPlayer())
|
||||||
return;
|
return;
|
||||||
|
@ -493,9 +493,9 @@ namespace MWMechanics
|
||||||
MWBase::Environment::get().getWorld()->isSwimming(actor) ||
|
MWBase::Environment::get().getWorld()->isSwimming(actor) ||
|
||||||
(packageId != AiPackage::TypeIdWander && packageId != AiPackage::TypeIdTravel && packageId != -1))
|
(packageId != AiPackage::TypeIdWander && packageId != AiPackage::TypeIdTravel && packageId != -1))
|
||||||
{
|
{
|
||||||
stats.setTurningToPlayer(false);
|
actorState.setTurningToPlayer(false);
|
||||||
stats.setGreetingTimer(0);
|
actorState.setGreetingTimer(0);
|
||||||
stats.setGreetingState(Greet_None);
|
actorState.setGreetingState(Greet_None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,14 +504,14 @@ namespace MWMechanics
|
||||||
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||||
osg::Vec3f dir = playerPos - actorPos;
|
osg::Vec3f dir = playerPos - actorPos;
|
||||||
|
|
||||||
if (stats.isTurningToPlayer())
|
if (actorState.isTurningToPlayer())
|
||||||
{
|
{
|
||||||
// Reduce the turning animation glitch by using a *HUGE* value of
|
// Reduce the turning animation glitch by using a *HUGE* value of
|
||||||
// epsilon... TODO: a proper fix might be in either the physics or the
|
// epsilon... TODO: a proper fix might be in either the physics or the
|
||||||
// animation subsystem
|
// animation subsystem
|
||||||
if (zTurn(actor, stats.getAngleToPlayer(), osg::DegreesToRadians(5.f)))
|
if (zTurn(actor, actorState.getAngleToPlayer(), osg::DegreesToRadians(5.f)))
|
||||||
{
|
{
|
||||||
stats.setTurningToPlayer(false);
|
actorState.setTurningToPlayer(false);
|
||||||
// An original engine launches an endless idle2 when an actor greets player.
|
// An original engine launches an endless idle2 when an actor greets player.
|
||||||
playAnimationGroup (actor, "idle2", 0, std::numeric_limits<int>::max(), false);
|
playAnimationGroup (actor, "idle2", 0, std::numeric_limits<int>::max(), false);
|
||||||
}
|
}
|
||||||
|
@ -526,8 +526,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
float helloDistance = static_cast<float>(stats.getAiSetting(CreatureStats::AI_Hello).getModified() * iGreetDistanceMultiplier);
|
float helloDistance = static_cast<float>(stats.getAiSetting(CreatureStats::AI_Hello).getModified() * iGreetDistanceMultiplier);
|
||||||
|
|
||||||
int greetingTimer = stats.getGreetingTimer();
|
int greetingTimer = actorState.getGreetingTimer();
|
||||||
GreetingState greetingState = stats.getGreetingState();
|
GreetingState greetingState = actorState.getGreetingState();
|
||||||
if (greetingState == Greet_None)
|
if (greetingState == Greet_None)
|
||||||
{
|
{
|
||||||
if ((playerPos - actorPos).length2() <= helloDistance*helloDistance &&
|
if ((playerPos - actorPos).length2() <= helloDistance*helloDistance &&
|
||||||
|
@ -549,7 +549,7 @@ namespace MWMechanics
|
||||||
greetingTimer++;
|
greetingTimer++;
|
||||||
|
|
||||||
if (greetingTimer <= GREETING_SHOULD_END || MWBase::Environment::get().getSoundManager()->sayActive(actor))
|
if (greetingTimer <= GREETING_SHOULD_END || MWBase::Environment::get().getSoundManager()->sayActive(actor))
|
||||||
turnActorToFacePlayer(actor, dir);
|
turnActorToFacePlayer(actor, actorState, dir);
|
||||||
|
|
||||||
if (greetingTimer >= GREETING_COOLDOWN)
|
if (greetingTimer >= GREETING_COOLDOWN)
|
||||||
{
|
{
|
||||||
|
@ -565,20 +565,19 @@ namespace MWMechanics
|
||||||
greetingState = Greet_None;
|
greetingState = Greet_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.setGreetingTimer(greetingTimer);
|
actorState.setGreetingTimer(greetingTimer);
|
||||||
stats.setGreetingState(greetingState);
|
actorState.setGreetingState(greetingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::turnActorToFacePlayer(const MWWorld::Ptr& actor, const osg::Vec3f& dir)
|
void Actors::turnActorToFacePlayer(const MWWorld::Ptr& actor, Actor& actorState, const osg::Vec3f& dir)
|
||||||
{
|
{
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[0] = 0;
|
actor.getClass().getMovementSettings(actor).mPosition[0] = 0;
|
||||||
|
|
||||||
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
if (!actorState.isTurningToPlayer())
|
||||||
if (!stats.isTurningToPlayer())
|
|
||||||
{
|
{
|
||||||
stats.setAngleToPlayer(std::atan2(dir.x(), dir.y()));
|
actorState.setAngleToPlayer(std::atan2(dir.x(), dir.y()));
|
||||||
stats.setTurningToPlayer(true);
|
actorState.setTurningToPlayer(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,6 +818,9 @@ namespace MWMechanics
|
||||||
if (visitor.mRemainingTime > 0)
|
if (visitor.mRemainingTime > 0)
|
||||||
{
|
{
|
||||||
double timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
double timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
||||||
|
if(timeScale == 0.0)
|
||||||
|
timeScale = 1;
|
||||||
|
|
||||||
restoreHours = std::max(0.0, hours - visitor.mRemainingTime * timeScale / 3600.f);
|
restoreHours = std::max(0.0, hours - visitor.mRemainingTime * timeScale / 3600.f);
|
||||||
}
|
}
|
||||||
else if (visitor.mRemainingTime == -1)
|
else if (visitor.mRemainingTime == -1)
|
||||||
|
@ -1782,6 +1784,8 @@ namespace MWMechanics
|
||||||
End of tes3mp change (major)
|
End of tes3mp change (major)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||||
|
|
||||||
// For dead actors we need to remove looping spell particles
|
// For dead actors we need to remove looping spell particles
|
||||||
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||||
ctrl->updateContinuousVfx();
|
ctrl->updateContinuousVfx();
|
||||||
|
@ -1862,7 +1866,7 @@ namespace MWMechanics
|
||||||
if (isConscious(iter->first))
|
if (isConscious(iter->first))
|
||||||
{
|
{
|
||||||
stats.getAiSequence().execute(iter->first, *ctrl, duration);
|
stats.getAiSequence().execute(iter->first, *ctrl, duration);
|
||||||
updateGreetingState(iter->first, timerUpdateHello > 0);
|
updateGreetingState(iter->first, *iter->second, timerUpdateHello > 0);
|
||||||
playIdleDialogue(iter->first);
|
playIdleDialogue(iter->first);
|
||||||
updateMovementSpeed(iter->first);
|
updateMovementSpeed(iter->first);
|
||||||
}
|
}
|
||||||
|
@ -2165,7 +2169,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
void Actors::rest(double hours, bool sleep)
|
void Actors::rest(double hours, bool sleep)
|
||||||
{
|
{
|
||||||
float duration = hours * 3600.f / MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
float duration = hours * 3600.f;
|
||||||
|
float timeScale = MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
||||||
|
if (timeScale != 0.f)
|
||||||
|
duration /= timeScale;
|
||||||
|
|
||||||
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||||
|
|
||||||
|
@ -2675,6 +2683,42 @@ namespace MWMechanics
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int Actors::getGreetingTimer(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return it->second->getGreetingTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Actors::getAngleToPlayer(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
return it->second->getAngleToPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
GreetingState Actors::getGreetingState(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return Greet_None;
|
||||||
|
|
||||||
|
return it->second->getGreetingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Actors::isTurningToPlayer(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return it->second->isTurningToPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::fastForwardAi()
|
void Actors::fastForwardAi()
|
||||||
{
|
{
|
||||||
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
@ -70,6 +72,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
PtrActorMap::const_iterator begin() { return mActors.begin(); }
|
PtrActorMap::const_iterator begin() { return mActors.begin(); }
|
||||||
PtrActorMap::const_iterator end() { return mActors.end(); }
|
PtrActorMap::const_iterator end() { return mActors.end(); }
|
||||||
|
std::size_t size() const { return mActors.size(); }
|
||||||
|
|
||||||
void notifyDied(const MWWorld::Ptr &actor);
|
void notifyDied(const MWWorld::Ptr &actor);
|
||||||
|
|
||||||
|
@ -122,8 +125,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void playIdleDialogue(const MWWorld::Ptr& actor);
|
void playIdleDialogue(const MWWorld::Ptr& actor);
|
||||||
void updateMovementSpeed(const MWWorld::Ptr& actor);
|
void updateMovementSpeed(const MWWorld::Ptr& actor);
|
||||||
void updateGreetingState(const MWWorld::Ptr& actor, bool turnOnly);
|
void updateGreetingState(const MWWorld::Ptr& actor, Actor& actorState, bool turnOnly);
|
||||||
void turnActorToFacePlayer(const MWWorld::Ptr& actor, const osg::Vec3f& dir);
|
void turnActorToFacePlayer(const MWWorld::Ptr& actor, Actor& actorState, const osg::Vec3f& dir);
|
||||||
|
|
||||||
void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor,
|
void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor,
|
||||||
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance);
|
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance);
|
||||||
|
@ -214,6 +217,11 @@ namespace MWMechanics
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int getGreetingTimer(const MWWorld::Ptr& ptr) const;
|
||||||
|
float getAngleToPlayer(const MWWorld::Ptr& ptr) const;
|
||||||
|
GreetingState getGreetingState(const MWWorld::Ptr& ptr) const;
|
||||||
|
bool isTurningToPlayer(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl);
|
void updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,13 @@ namespace MWWorld
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
enum GreetingState
|
||||||
|
{
|
||||||
|
Greet_None,
|
||||||
|
Greet_InProgress,
|
||||||
|
Greet_Done
|
||||||
|
};
|
||||||
|
|
||||||
MWWorld::Ptr getPlayer();
|
MWWorld::Ptr getPlayer();
|
||||||
bool isPlayerInCombat();
|
bool isPlayerInCombat();
|
||||||
bool canActorMoveByZAxis(const MWWorld::Ptr& actor);
|
bool canActorMoveByZAxis(const MWWorld::Ptr& actor);
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief Causes actor to walk to activatable object and activate it
|
/// \brief Causes actor to walk to activatable object and activate it
|
||||||
/** Will activate when close to object **/
|
/** Will activate when close to object **/
|
||||||
class AiActivate : public AiPackage
|
class AiActivate final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
@ -49,11 +49,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
||||||
|
|
||||||
virtual AiActivate *clone() const;
|
AiActivate *clone() const final;
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual void writeState(ESM::AiSequence::AiSequence& sequence) const;
|
void writeState(ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mObjectId;
|
std::string mObjectId;
|
||||||
|
|
|
@ -16,22 +16,22 @@ namespace MWMechanics
|
||||||
/// \brief AiPackage to have an actor avoid an opening door
|
/// \brief AiPackage to have an actor avoid an opening door
|
||||||
/** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it
|
/** The AI will retreat from the door until it has finished opening, walked far away from it, or one second has passed, in an attempt to avoid it
|
||||||
**/
|
**/
|
||||||
class AiAvoidDoor : public AiPackage
|
class AiAvoidDoor final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Avoid door until the door is fully open
|
/// Avoid door until the door is fully open
|
||||||
AiAvoidDoor(const MWWorld::ConstPtr& doorPtr);
|
AiAvoidDoor(const MWWorld::ConstPtr& doorPtr);
|
||||||
|
|
||||||
virtual AiAvoidDoor *clone() const;
|
AiAvoidDoor *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual unsigned int getPriority() const;
|
unsigned int getPriority() const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mDuration;
|
float mDuration;
|
||||||
|
|
|
@ -7,21 +7,21 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief AiPackage to have an actor resurface to breathe
|
/// \brief AiPackage to have an actor resurface to breathe
|
||||||
// The AI will go up if lesser than half breath left
|
// The AI will go up if lesser than half breath left
|
||||||
class AiBreathe : public AiPackage
|
class AiBreathe final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AiBreathe();
|
AiBreathe();
|
||||||
|
|
||||||
virtual AiBreathe *clone() const;
|
AiBreathe *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual unsigned int getPriority() const;
|
unsigned int getPriority() const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,22 +11,22 @@ namespace MWWorld
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// AiPackage which makes an actor to cast given spell.
|
/// AiPackage which makes an actor to cast given spell.
|
||||||
class AiCast : public AiPackage {
|
class AiCast final : public AiPackage {
|
||||||
public:
|
public:
|
||||||
AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell=false);
|
AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell=false);
|
||||||
|
|
||||||
virtual AiPackage *clone() const;
|
AiPackage *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual MWWorld::Ptr getTarget() const;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
virtual unsigned int getPriority() const;
|
unsigned int getPriority() const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mTargetId;
|
std::string mTargetId;
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace MWMechanics
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Causes the actor to fight another actor
|
/// \brief Causes the actor to fight another actor
|
||||||
class AiCombat : public AiPackage
|
class AiCombat final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///Constructor
|
///Constructor
|
||||||
|
@ -102,21 +102,21 @@ namespace MWMechanics
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
virtual AiCombat *clone() const;
|
AiCombat *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual unsigned int getPriority() const;
|
unsigned int getPriority() const final;
|
||||||
|
|
||||||
///Returns target ID
|
///Returns target ID
|
||||||
MWWorld::Ptr getTarget() const;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Returns true if combat should end
|
/// Returns true if combat should end
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace AiSequence
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief AI Package to have an NPC lead the player to a specific point
|
/// \brief AI Package to have an NPC lead the player to a specific point
|
||||||
class AiEscort : public AiPackage
|
class AiEscort final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Implementation of AiEscort
|
/// Implementation of AiEscort
|
||||||
|
@ -30,21 +30,21 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiEscort(const ESM::AiSequence::AiEscort* escort);
|
AiEscort(const ESM::AiSequence::AiEscort* escort);
|
||||||
|
|
||||||
virtual AiEscort *clone() const;
|
AiEscort *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual bool useVariableSpeed() const { return true;}
|
bool useVariableSpeed() const final { return true; }
|
||||||
|
|
||||||
virtual bool sideWithTarget() const { return true; }
|
bool sideWithTarget() const final { return true; }
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(mX, mY, mZ); }
|
osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mCellId;
|
std::string mCellId;
|
||||||
|
|
|
@ -6,20 +6,20 @@
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// AiPackage which makes an actor face a certain direction.
|
/// AiPackage which makes an actor face a certain direction.
|
||||||
class AiFace : public AiPackage {
|
class AiFace final : public AiPackage {
|
||||||
public:
|
public:
|
||||||
AiFace(float targetX, float targetY);
|
AiFace(float targetX, float targetY);
|
||||||
|
|
||||||
virtual AiPackage *clone() const;
|
AiPackage *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual unsigned int getPriority() const;
|
unsigned int getPriority() const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mTargetX, mTargetY;
|
float mTargetX, mTargetY;
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace MWMechanics
|
||||||
/// \brief AiPackage for an actor to follow another actor/the PC
|
/// \brief AiPackage for an actor to follow another actor/the PC
|
||||||
/** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely
|
/** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely
|
||||||
**/
|
**/
|
||||||
class AiFollow : public AiPackage
|
class AiFollow final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AiFollow(const std::string &actorId, float duration, float x, float y, float z);
|
AiFollow(const std::string &actorId, float duration, float x, float y, float z);
|
||||||
|
@ -53,30 +53,30 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiFollow(const ESM::AiSequence::AiFollow* follow);
|
AiFollow(const ESM::AiSequence::AiFollow* follow);
|
||||||
|
|
||||||
virtual bool sideWithTarget() const { return true; }
|
bool sideWithTarget() const final { return true; }
|
||||||
virtual bool followTargetThroughDoors() const { return true; }
|
bool followTargetThroughDoors() const final { return true; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return !mCommanded; }
|
bool shouldCancelPreviousAi() const final { return !mCommanded; }
|
||||||
|
|
||||||
virtual AiFollow *clone() const;
|
AiFollow *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual bool useVariableSpeed() const { return true;}
|
bool useVariableSpeed() const final { return true; }
|
||||||
|
|
||||||
/// Returns the actor being followed
|
/// Returns the actor being followed
|
||||||
std::string getFollowedActor();
|
std::string getFollowedActor();
|
||||||
|
|
||||||
virtual void writeState (ESM::AiSequence::AiSequence& sequence) const;
|
void writeState (ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
bool isCommanded() const;
|
bool isCommanded() const;
|
||||||
|
|
||||||
int getFollowIndex() const;
|
int getFollowIndex() const;
|
||||||
|
|
||||||
void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination() const
|
osg::Vec3f getDestination() const final
|
||||||
{
|
{
|
||||||
MWWorld::Ptr target = getTarget();
|
MWWorld::Ptr target = getTarget();
|
||||||
if (target.isEmpty())
|
if (target.isEmpty())
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
|
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
|
|
||||||
MWMechanics::AiPackage::~AiPackage() {}
|
|
||||||
|
|
||||||
MWMechanics::AiPackage::AiPackage() :
|
MWMechanics::AiPackage::AiPackage() :
|
||||||
mTimer(AI_REACTION_TIME + 1.0f), // to force initial pathbuild
|
mTimer(AI_REACTION_TIME + 1.0f), // to force initial pathbuild
|
||||||
mTargetActorRefId(""),
|
mTargetActorRefId(""),
|
||||||
|
|
|
@ -56,8 +56,7 @@ namespace MWMechanics
|
||||||
///Default constructor
|
///Default constructor
|
||||||
AiPackage();
|
AiPackage();
|
||||||
|
|
||||||
///Default Deconstructor
|
virtual ~AiPackage() = default;
|
||||||
virtual ~AiPackage();
|
|
||||||
|
|
||||||
///Clones the package
|
///Clones the package
|
||||||
virtual AiPackage *clone() const = 0;
|
virtual AiPackage *clone() const = 0;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace MWMechanics
|
||||||
/** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them.
|
/** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them.
|
||||||
Note that while very similar to AiActivate, it will ONLY activate when evry close to target (Not also when the
|
Note that while very similar to AiActivate, it will ONLY activate when evry close to target (Not also when the
|
||||||
path is completed). **/
|
path is completed). **/
|
||||||
class AiPursue : public AiPackage
|
class AiPursue final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///Constructor
|
///Constructor
|
||||||
|
@ -26,16 +26,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiPursue(const ESM::AiSequence::AiPursue* pursue);
|
AiPursue(const ESM::AiSequence::AiPursue* pursue);
|
||||||
|
|
||||||
virtual AiPursue *clone() const;
|
AiPursue *clone() const final;
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
MWWorld::Ptr getTarget() const;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
virtual void writeState (ESM::AiSequence::AiSequence& sequence) const;
|
void writeState (ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
virtual bool canCancel() const { return false; }
|
bool canCancel() const final { return false; }
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
bool shouldCancelPreviousAi() const final { return false; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -212,7 +212,8 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiPackage* package = mPackages.front();
|
auto packageIt = mPackages.begin();
|
||||||
|
MWMechanics::AiPackage* package = *packageIt;
|
||||||
if (!package->alwaysActive() && outOfRange)
|
if (!package->alwaysActive() && outOfRange)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -223,7 +224,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||||
// if active package is combat one, choose nearest target
|
// if active package is combat one, choose nearest target
|
||||||
if (packageTypeId == AiPackage::TypeIdCombat)
|
if (packageTypeId == AiPackage::TypeIdCombat)
|
||||||
{
|
{
|
||||||
std::list<AiPackage *>::iterator itActualCombat;
|
auto itActualCombat = mPackages.end();
|
||||||
|
|
||||||
float nearestDist = std::numeric_limits<float>::max();
|
float nearestDist = std::numeric_limits<float>::max();
|
||||||
osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
|
osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
|
||||||
|
@ -265,16 +266,18 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPackages.empty())
|
assert(!mPackages.empty());
|
||||||
{
|
|
||||||
if (nearestDist < std::numeric_limits<float>::max() && mPackages.begin() != itActualCombat)
|
if (nearestDist < std::numeric_limits<float>::max() && mPackages.begin() != itActualCombat)
|
||||||
{
|
{
|
||||||
|
assert(itActualCombat != mPackages.end());
|
||||||
// move combat package with nearest target to the front
|
// move combat package with nearest target to the front
|
||||||
mPackages.splice(mPackages.begin(), mPackages, itActualCombat);
|
mPackages.splice(mPackages.begin(), mPackages, itActualCombat);
|
||||||
}
|
}
|
||||||
|
|
||||||
package = mPackages.front();
|
packageIt = mPackages.begin();
|
||||||
}
|
package = *packageIt;
|
||||||
|
packageTypeId = package->getTypeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -289,9 +292,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||||
}
|
}
|
||||||
// To account for the rare case where AiPackage::execute() queued another AI package
|
// To account for the rare case where AiPackage::execute() queued another AI package
|
||||||
// (e.g. AiPursue executing a dialogue script that uses startCombat)
|
// (e.g. AiPursue executing a dialogue script that uses startCombat)
|
||||||
std::list<MWMechanics::AiPackage*>::iterator toRemove =
|
mPackages.erase(packageIt);
|
||||||
std::find(mPackages.begin(), mPackages.end(), package);
|
|
||||||
mPackages.erase(toRemove);
|
|
||||||
delete package;
|
delete package;
|
||||||
if (isActualAiPackage(packageTypeId))
|
if (isActualAiPackage(packageTypeId))
|
||||||
mDone = true;
|
mDone = true;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -43,14 +44,15 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool AiTravel::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
bool AiTravel::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
||||||
{
|
{
|
||||||
auto& stats = actor.getClass().getCreatureStats(actor);
|
MWBase::MechanicsManager* mechMgr = MWBase::Environment::get().getMechanicsManager();
|
||||||
|
|
||||||
if (stats.isTurningToPlayer() || stats.getGreetingState() == Greet_InProgress)
|
if (mechMgr->isTurningToPlayer(actor) || mechMgr->getGreetingState(actor) == Greet_InProgress)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
const osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||||
const osg::Vec3f targetPos(mX, mY, mZ);
|
const osg::Vec3f targetPos(mX, mY, mZ);
|
||||||
|
|
||||||
|
auto& stats = actor.getClass().getCreatureStats(actor);
|
||||||
stats.setMovementFlag(CreatureStats::Flag_Run, false);
|
stats.setMovementFlag(CreatureStats::Flag_Run, false);
|
||||||
stats.setDrawState(DrawState_Nothing);
|
stats.setDrawState(DrawState_Nothing);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace AiSequence
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief Causes the AI to travel to the specified point
|
/// \brief Causes the AI to travel to the specified point
|
||||||
class AiTravel : public AiPackage
|
class AiTravel final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
|
@ -22,21 +22,21 @@ namespace MWMechanics
|
||||||
AiTravel(const ESM::AiSequence::AiTravel* travel);
|
AiTravel(const ESM::AiSequence::AiTravel* travel);
|
||||||
|
|
||||||
/// Simulates the passing of time
|
/// Simulates the passing of time
|
||||||
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
||||||
|
|
||||||
void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
virtual AiTravel *clone() const;
|
AiTravel *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual bool useVariableSpeed() const { return true;}
|
bool useVariableSpeed() const final { return true; }
|
||||||
|
|
||||||
virtual bool alwaysActive() const { return true; }
|
bool alwaysActive() const final { return true; }
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(mX, mY, mZ); }
|
osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mX;
|
float mX;
|
||||||
|
|
|
@ -89,6 +89,11 @@ namespace MWMechanics
|
||||||
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
const auto maxHalfExtent = std::max(halfExtents.x(), std::max(halfExtents.y(), halfExtents.z()));
|
||||||
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor);
|
return world->isAreaOccupiedByOtherActor(destination, 2 * maxHalfExtent, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stopMovement(const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||||
|
@ -165,7 +170,7 @@ namespace MWMechanics
|
||||||
* actors will enter combat (i.e. no longer wandering) and different pathfinding
|
* actors will enter combat (i.e. no longer wandering) and different pathfinding
|
||||||
* will kick in.
|
* will kick in.
|
||||||
*/
|
*/
|
||||||
bool AiWander::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
bool AiWander::execute (const MWWorld::Ptr& actor, CharacterController& /*characterController*/, AiState& state, float duration)
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
||||||
if (cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
|
if (cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
|
||||||
|
@ -201,12 +206,12 @@ namespace MWMechanics
|
||||||
storage.setState(AiWanderStorage::Wander_Walking);
|
storage.setState(AiWanderStorage::Wander_Walking);
|
||||||
}
|
}
|
||||||
|
|
||||||
GreetingState greetingState = cStats.getGreetingState();
|
GreetingState greetingState = MWBase::Environment::get().getMechanicsManager()->getGreetingState(actor);
|
||||||
if (greetingState == Greet_InProgress)
|
if (greetingState == Greet_InProgress)
|
||||||
{
|
{
|
||||||
if (storage.mState == AiWanderStorage::Wander_Walking)
|
if (storage.mState == AiWanderStorage::Wander_Walking)
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage, false);
|
stopMovement(actor);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.setState(AiWanderStorage::Wander_IdleNow);
|
storage.setState(AiWanderStorage::Wander_IdleNow);
|
||||||
}
|
}
|
||||||
|
@ -230,8 +235,9 @@ namespace MWMechanics
|
||||||
if (mDistance <= 0)
|
if (mDistance <= 0)
|
||||||
storage.mCanWanderAlongPathGrid = false;
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
|
||||||
if (isPackageCompleted(actor, storage))
|
if (isPackageCompleted())
|
||||||
{
|
{
|
||||||
|
stopWalking(actor);
|
||||||
// Reset package so it can be used again
|
// Reset package so it can be used again
|
||||||
mRemainingDuration=mDuration;
|
mRemainingDuration=mDuration;
|
||||||
init();
|
init();
|
||||||
|
@ -315,19 +321,10 @@ namespace MWMechanics
|
||||||
return actor.getRefData().getPosition().asVec3();
|
return actor.getRefData().getPosition().asVec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage)
|
bool AiWander::isPackageCompleted() const
|
||||||
{
|
|
||||||
if (mDuration)
|
|
||||||
{
|
{
|
||||||
// End package if duration is complete
|
// End package if duration is complete
|
||||||
if (mRemainingDuration <= 0)
|
return mDuration && mRemainingDuration <= 0;
|
||||||
{
|
|
||||||
stopWalking(actor, storage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if get here, not yet completed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -395,7 +392,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
|
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.setState(AiWanderStorage::Wander_IdleNow);
|
storage.setState(AiWanderStorage::Wander_IdleNow);
|
||||||
}
|
}
|
||||||
|
@ -445,7 +442,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if idle animation finished
|
// Check if idle animation finished
|
||||||
GreetingState greetingState = actor.getClass().getCreatureStats(actor).getGreetingState();
|
GreetingState greetingState = MWBase::Environment::get().getMechanicsManager()->getGreetingState(actor);
|
||||||
if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
|
if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
|
||||||
{
|
{
|
||||||
if (mPathFinder.isPathConstructed())
|
if (mPathFinder.isPathConstructed())
|
||||||
|
@ -460,13 +457,13 @@ namespace MWMechanics
|
||||||
// Is there no destination or are we there yet?
|
// Is there no destination or are we there yet?
|
||||||
if ((!mPathFinder.isPathConstructed()) || pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE))
|
if ((!mPathFinder.isPathConstructed()) || pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE))
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor);
|
||||||
storage.setState(AiWanderStorage::Wander_ChooseAction);
|
storage.setState(AiWanderStorage::Wander_ChooseAction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// have not yet reached the destination
|
// have not yet reached the destination
|
||||||
evadeObstacles(actor, duration, storage);
|
evadeObstacles(actor, storage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,15 +494,12 @@ namespace MWMechanics
|
||||||
storage.setState(AiWanderStorage::Wander_IdleNow);
|
storage.setState(AiWanderStorage::Wander_IdleNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage)
|
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage)
|
||||||
{
|
{
|
||||||
if (mUsePathgrid)
|
if (mUsePathgrid)
|
||||||
{
|
{
|
||||||
const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
|
const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
|
||||||
const float actorTolerance = 2 * actor.getClass().getSpeed(actor) * duration
|
mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor));
|
||||||
+ 1.2 * std::max(halfExtents.x(), halfExtents.y());
|
|
||||||
const float pointTolerance = std::max(MIN_TOLERANCE, actorTolerance);
|
|
||||||
mPathFinder.buildPathByNavMeshToNextPoint(actor, halfExtents, getNavigatorFlags(actor), pointTolerance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mObstacleCheck.isEvading())
|
if (mObstacleCheck.isEvading())
|
||||||
|
@ -518,7 +512,7 @@ namespace MWMechanics
|
||||||
storage.mTrimCurrentNode = true;
|
storage.mTrimCurrentNode = true;
|
||||||
trimAllowedNodes(storage.mAllowedNodes, mPathFinder);
|
trimAllowedNodes(storage.mAllowedNodes, mPathFinder);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor);
|
||||||
storage.setState(AiWanderStorage::Wander_MoveNow);
|
storage.setState(AiWanderStorage::Wander_MoveNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +523,7 @@ namespace MWMechanics
|
||||||
if (storage.mStuckCount >= getCountBeforeReset(actor)) // something has gone wrong, reset
|
if (storage.mStuckCount >= getCountBeforeReset(actor)) // something has gone wrong, reset
|
||||||
{
|
{
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor);
|
||||||
storage.setState(AiWanderStorage::Wander_ChooseAction);
|
storage.setState(AiWanderStorage::Wander_ChooseAction);
|
||||||
storage.mStuckCount = 0;
|
storage.mStuckCount = 0;
|
||||||
}
|
}
|
||||||
|
@ -609,14 +603,11 @@ namespace MWMechanics
|
||||||
return TypeIdWander;
|
return TypeIdWander;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath)
|
void AiWander::stopWalking(const MWWorld::Ptr& actor)
|
||||||
{
|
|
||||||
if (clearPath)
|
|
||||||
{
|
{
|
||||||
mPathFinder.clearPath();
|
mPathFinder.clearPath();
|
||||||
mHasDestination = false;
|
mHasDestination = false;
|
||||||
}
|
stopMovement(actor);
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace MWMechanics
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Causes the Actor to wander within a specified range
|
/// \brief Causes the Actor to wander within a specified range
|
||||||
class AiWander : public AiPackage
|
class AiWander final : public AiPackage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
@ -91,23 +91,23 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiWander (const ESM::AiSequence::AiWander* wander);
|
AiWander (const ESM::AiSequence::AiWander* wander);
|
||||||
|
|
||||||
virtual AiPackage *clone() const;
|
AiPackage *clone() const final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
int getTypeId() const final;
|
||||||
|
|
||||||
virtual bool useVariableSpeed() const { return true;}
|
bool useVariableSpeed() const final { return true; }
|
||||||
|
|
||||||
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
void writeState(ESM::AiSequence::AiSequence &sequence) const final;
|
||||||
|
|
||||||
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
|
void fastForward(const MWWorld::Ptr& actor, AiState& state) final;
|
||||||
|
|
||||||
bool getRepeat() const;
|
bool getRepeat() const final;
|
||||||
|
|
||||||
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const;
|
osg::Vec3f getDestination(const MWWorld::Ptr& actor) const final;
|
||||||
|
|
||||||
virtual osg::Vec3f getDestination() const
|
osg::Vec3f getDestination() const final
|
||||||
{
|
{
|
||||||
if (!mHasDestination)
|
if (!mHasDestination)
|
||||||
return osg::Vec3f(0, 0, 0);
|
return osg::Vec3f(0, 0, 0);
|
||||||
|
@ -118,7 +118,7 @@ namespace MWMechanics
|
||||||
private:
|
private:
|
||||||
// NOTE: mDistance and mDuration must be set already
|
// NOTE: mDistance and mDuration must be set already
|
||||||
void init();
|
void init();
|
||||||
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath = true);
|
void stopWalking(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
/// Have the given actor play an idle animation
|
/// Have the given actor play an idle animation
|
||||||
/// @return Success or error
|
/// @return Success or error
|
||||||
|
@ -126,14 +126,14 @@ namespace MWMechanics
|
||||||
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
||||||
short unsigned getRandomIdle();
|
short unsigned getRandomIdle();
|
||||||
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
||||||
void evadeObstacles(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
|
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
|
||||||
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
inline bool isPackageCompleted() const;
|
||||||
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
||||||
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
|
bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination);
|
||||||
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
|
void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage);
|
||||||
|
|
|
@ -262,6 +262,8 @@ namespace MWMechanics
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||||
duration = effect.mDuration;
|
duration = effect.mDuration;
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::AppliedOnce))
|
||||||
|
duration = std::max(1, duration);
|
||||||
|
|
||||||
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
|
||||||
.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
|
.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
|
||||||
|
|
|
@ -1013,7 +1013,7 @@ void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, const std::multimap<float, std::string> &map)
|
void CharacterController::handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map)
|
||||||
{
|
{
|
||||||
const std::string &evt = key->second;
|
const std::string &evt = key->second;
|
||||||
|
|
||||||
|
@ -1368,10 +1368,9 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use blending only with 3d-person movement animations for bipedal actors
|
// For biped actors, blend weapon animations with lower body animations with higher priority
|
||||||
bool firstPersonPlayer = (mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson());
|
|
||||||
MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon);
|
MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon);
|
||||||
if (!firstPersonPlayer && mPtr.getClass().isBipedal(mPtr))
|
if (mPtr.getClass().isBipedal(mPtr))
|
||||||
priorityWeapon[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody;
|
priorityWeapon[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody;
|
||||||
|
|
||||||
bool forcestateupdate = false;
|
bool forcestateupdate = false;
|
||||||
|
|
|
@ -238,8 +238,7 @@ public:
|
||||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||||
virtual ~CharacterController();
|
virtual ~CharacterController();
|
||||||
|
|
||||||
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map);
|
||||||
const std::multimap<float, std::string>& map);
|
|
||||||
|
|
||||||
// Be careful when to call this, see comment in Actors
|
// Be careful when to call this, see comment in Actors
|
||||||
void updateContinuousVfx();
|
void updateContinuousVfx();
|
||||||
|
|
|
@ -34,53 +34,12 @@ namespace MWMechanics
|
||||||
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
|
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
|
||||||
mHitRecovery(false), mBlock(false), mMovementFlags(0),
|
mHitRecovery(false), mBlock(false), mMovementFlags(0),
|
||||||
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1),
|
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1),
|
||||||
mDeathAnimation(-1), mTimeOfDeath(), mGreetingState(Greet_None),
|
mDeathAnimation(-1), mTimeOfDeath(), mLevel (0)
|
||||||
mGreetingTimer(0), mTargetAngleRadians(0), mIsTurningToPlayer(false), mLevel (0)
|
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mAiSettings[i] = 0;
|
mAiSettings[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::CreatureStats::getGreetingTimer() const
|
|
||||||
{
|
|
||||||
return mGreetingTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWMechanics::CreatureStats::setGreetingTimer(int timer)
|
|
||||||
{
|
|
||||||
mGreetingTimer = timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MWMechanics::CreatureStats::getAngleToPlayer() const
|
|
||||||
{
|
|
||||||
return mTargetAngleRadians;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWMechanics::CreatureStats::setAngleToPlayer(float angle)
|
|
||||||
{
|
|
||||||
mTargetAngleRadians = angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
GreetingState MWMechanics::CreatureStats::getGreetingState() const
|
|
||||||
{
|
|
||||||
return mGreetingState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWMechanics::CreatureStats::setGreetingState(GreetingState state)
|
|
||||||
{
|
|
||||||
mGreetingState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::CreatureStats::isTurningToPlayer() const
|
|
||||||
{
|
|
||||||
return mIsTurningToPlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWMechanics::CreatureStats::setTurningToPlayer(bool turning)
|
|
||||||
{
|
|
||||||
mIsTurningToPlayer = turning;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AiSequence& CreatureStats::getAiSequence() const
|
const AiSequence& CreatureStats::getAiSequence() const
|
||||||
{
|
{
|
||||||
return mAiSequence;
|
return mAiSequence;
|
||||||
|
|
|
@ -19,13 +19,6 @@ namespace ESM
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
enum GreetingState
|
|
||||||
{
|
|
||||||
Greet_None,
|
|
||||||
Greet_InProgress,
|
|
||||||
Greet_Done
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Common creature stats
|
/// \brief Common creature stats
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
@ -77,11 +70,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
MWWorld::TimeStamp mTimeOfDeath;
|
MWWorld::TimeStamp mTimeOfDeath;
|
||||||
|
|
||||||
GreetingState mGreetingState;
|
|
||||||
int mGreetingTimer;
|
|
||||||
float mTargetAngleRadians;
|
|
||||||
bool mIsTurningToPlayer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<int, std::string> SummonKey; // <ESM::MagicEffect index, spell ID>
|
typedef std::pair<int, std::string> SummonKey; // <ESM::MagicEffect index, spell ID>
|
||||||
private:
|
private:
|
||||||
|
@ -97,18 +85,6 @@ namespace MWMechanics
|
||||||
public:
|
public:
|
||||||
CreatureStats();
|
CreatureStats();
|
||||||
|
|
||||||
int getGreetingTimer() const;
|
|
||||||
void setGreetingTimer(int timer);
|
|
||||||
|
|
||||||
float getAngleToPlayer() const;
|
|
||||||
void setAngleToPlayer(float angle);
|
|
||||||
|
|
||||||
GreetingState getGreetingState() const;
|
|
||||||
void setGreetingState(GreetingState state);
|
|
||||||
|
|
||||||
bool isTurningToPlayer() const;
|
|
||||||
void setTurningToPlayer(bool turning);
|
|
||||||
|
|
||||||
DrawState_ getDrawState() const;
|
DrawState_ getDrawState() const;
|
||||||
void setDrawState(DrawState_ state);
|
void setDrawState(DrawState_ state);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "mechanicsmanagerimp.hpp"
|
#include "mechanicsmanagerimp.hpp"
|
||||||
|
|
||||||
|
#include <osg/Stats>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
@ -2097,4 +2099,29 @@ namespace MWMechanics
|
||||||
mActors.cleanupSummonedCreature(caster.getClass().getCreatureStats(caster), creatureActorId);
|
mActors.cleanupSummonedCreature(caster.getClass().getCreatureStats(caster), creatureActorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MechanicsManager::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
stats.setAttribute(frameNumber, "Mechanics Actors", mActors.size());
|
||||||
|
stats.setAttribute(frameNumber, "Mechanics Objects", mObjects.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int MechanicsManager::getGreetingTimer(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.getGreetingTimer(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MechanicsManager::getAngleToPlayer(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.getAngleToPlayer(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
GreetingState MechanicsManager::getGreetingState(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.getGreetingState(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isTurningToPlayer(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.isTurningToPlayer(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,13 @@ namespace MWMechanics
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr) override;
|
virtual bool isRunning(const MWWorld::Ptr& ptr) override;
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr) override;
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) override;
|
||||||
|
|
||||||
|
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
||||||
|
|
||||||
|
virtual int getGreetingTimer(const MWWorld::Ptr& ptr) const override;
|
||||||
|
virtual float getAngleToPlayer(const MWWorld::Ptr& ptr) const override;
|
||||||
|
virtual GreetingState getGreetingState(const MWWorld::Ptr& ptr) const override;
|
||||||
|
virtual bool isTurningToPlayer(const MWWorld::Ptr& ptr) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool canCommitCrimeAgainst(const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
bool canCommitCrimeAgainst(const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
||||||
bool canReportCrime(const MWWorld::Ptr &actor, const MWWorld::Ptr &victim, std::set<MWWorld::Ptr> &playerFollowers);
|
bool canReportCrime(const MWWorld::Ptr &actor, const MWWorld::Ptr &victim, std::set<MWWorld::Ptr> &playerFollowers);
|
||||||
|
|
|
@ -52,6 +52,11 @@ namespace MWMechanics
|
||||||
void persistAnimationStates();
|
void persistAnimationStates();
|
||||||
|
|
||||||
void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out);
|
void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out);
|
||||||
|
|
||||||
|
std::size_t size() const
|
||||||
|
{
|
||||||
|
return mObjects.size();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||||
const DetourNavigator::Flags flags, const float pointTolerance)
|
const DetourNavigator::Flags flags)
|
||||||
{
|
{
|
||||||
if (mPath.empty())
|
if (mPath.empty())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace MWMechanics
|
||||||
const DetourNavigator::Flags flags);
|
const DetourNavigator::Flags flags);
|
||||||
|
|
||||||
void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
void buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents,
|
||||||
const DetourNavigator::Flags flags, const float pointTolerance);
|
const DetourNavigator::Flags flags);
|
||||||
|
|
||||||
/// Remove front point if exist and within tolerance
|
/// Remove front point if exist and within tolerance
|
||||||
void update(const osg::Vec3f& position, const float pointTolerance, const float destinationTolerance);
|
void update(const osg::Vec3f& position, const float pointTolerance, const float destinationTolerance);
|
||||||
|
|
|
@ -200,6 +200,7 @@ namespace MWMechanics
|
||||||
effect.mEffectId = effectIt->mEffectID;
|
effect.mEffectId = effectIt->mEffectID;
|
||||||
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
||||||
effect.mMagnitude = magnitude;
|
effect.mMagnitude = magnitude;
|
||||||
|
effect.mTimeLeft = 0.f;
|
||||||
|
|
||||||
// Avoid applying absorb effects if the caster is the target
|
// Avoid applying absorb effects if the caster is the target
|
||||||
// We still need the spell to be added
|
// We still need the spell to be added
|
||||||
|
@ -224,10 +225,15 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||||
if (hasDuration && effectIt->mDuration == 0)
|
effect.mDuration = hasDuration ? static_cast<float>(effectIt->mDuration) : 1.f;
|
||||||
|
|
||||||
|
bool appliedOnce = magicEffect->mData.mFlags & ESM::MagicEffect::AppliedOnce;
|
||||||
|
if (!appliedOnce)
|
||||||
|
effect.mDuration = std::max(1.f, effect.mDuration);
|
||||||
|
|
||||||
|
if (effect.mDuration == 0)
|
||||||
{
|
{
|
||||||
// We still should add effect to list to allow GetSpellEffects to detect this spell
|
// We still should add effect to list to allow GetSpellEffects to detect this spell
|
||||||
effect.mDuration = 0.f;
|
|
||||||
appliedLastingEffects.push_back(effect);
|
appliedLastingEffects.push_back(effect);
|
||||||
|
|
||||||
// duration 0 means apply full magnitude instantly
|
// duration 0 means apply full magnitude instantly
|
||||||
|
@ -264,7 +270,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
effect.mDuration = hasDuration ? static_cast<float>(effectIt->mDuration) : 1.f;
|
effect.mTimeLeft = effect.mDuration;
|
||||||
|
|
||||||
targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude));
|
targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude));
|
||||||
|
|
||||||
|
|
|
@ -394,8 +394,9 @@ namespace MWMechanics
|
||||||
priority = 10;
|
priority = 10;
|
||||||
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
const DynamicStat<float>& current = stats.getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
|
const DynamicStat<float>& current = stats.getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
|
||||||
|
// NB: this currently assumes the hardcoded magic effect flags are used
|
||||||
const float magnitude = (effect.mMagnMin + effect.mMagnMax)/2.f;
|
const float magnitude = (effect.mMagnMin + effect.mMagnMax)/2.f;
|
||||||
const float toHeal = magnitude * effect.mDuration;
|
const float toHeal = magnitude * std::max(1, effect.mDuration);
|
||||||
// Effect doesn't heal more than we need, *or* we are below 1/2 health
|
// Effect doesn't heal more than we need, *or* we are below 1/2 health
|
||||||
if (current.getModified() - current.getCurrent() > toHeal
|
if (current.getModified() - current.getCurrent() > toHeal
|
||||||
|| current.getCurrent() < current.getModified()*0.5)
|
|| current.getCurrent() < current.getModified()*0.5)
|
||||||
|
|
|
@ -31,9 +31,12 @@ namespace MWMechanics
|
||||||
magicEffect = store.get<ESM::MagicEffect>().find(effect.mEffectID);
|
magicEffect = store.get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
bool hasMagnitude = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude);
|
bool hasMagnitude = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude);
|
||||||
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||||
|
bool appliedOnce = magicEffect->mData.mFlags & ESM::MagicEffect::AppliedOnce;
|
||||||
int minMagn = hasMagnitude ? effect.mMagnMin : 1;
|
int minMagn = hasMagnitude ? effect.mMagnMin : 1;
|
||||||
int maxMagn = hasMagnitude ? effect.mMagnMax : 1;
|
int maxMagn = hasMagnitude ? effect.mMagnMax : 1;
|
||||||
int duration = hasDuration ? effect.mDuration : 1;
|
int duration = hasDuration ? effect.mDuration : 1;
|
||||||
|
if (!appliedOnce)
|
||||||
|
duration = std::max(1, duration);
|
||||||
static const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
|
static const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
|
||||||
|
|
||||||
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
|
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "physicssystem.hpp"
|
#include "physicssystem.hpp"
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
#include <osg/Stats>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btConeShape.h>
|
#include <BulletCollision/CollisionShapes/btConeShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btSphereShape.h>
|
#include <BulletCollision/CollisionShapes/btSphereShape.h>
|
||||||
|
@ -669,7 +670,7 @@ namespace MWPhysics
|
||||||
bool cmode = found->second->getCollisionMode();
|
bool cmode = found->second->getCollisionMode();
|
||||||
cmode = !cmode;
|
cmode = !cmode;
|
||||||
found->second->enableCollisionMode(cmode);
|
found->second->enableCollisionMode(cmode);
|
||||||
found->second->enableCollisionBody(cmode);
|
// NB: Collision body isn't disabled for vanilla TCL compatibility
|
||||||
return cmode;
|
return cmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,4 +906,11 @@ namespace MWPhysics
|
||||||
mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback);
|
mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback);
|
||||||
return callback.getResult();
|
return callback.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
stats.setAttribute(frameNumber, "Physics Actors", mActors.size());
|
||||||
|
stats.setAttribute(frameNumber, "Physics Objects", mObjects.size());
|
||||||
|
stats.setAttribute(frameNumber, "Physics HeightFields", mHeightFields.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace osg
|
||||||
{
|
{
|
||||||
class Group;
|
class Group;
|
||||||
class Object;
|
class Object;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -196,6 +197,8 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const;
|
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const;
|
||||||
|
|
||||||
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateWater();
|
void updateWater();
|
||||||
|
|
|
@ -151,20 +151,8 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
|
float calcAnimVelocity(const NifOsg::TextKeyMap& keys, NifOsg::KeyframeController *nonaccumctrl,
|
||||||
{
|
const osg::Vec3f& accum, const std::string &groupname)
|
||||||
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
|
|
||||||
for(;iter != keys.end();++iter)
|
|
||||||
{
|
|
||||||
if(iter->second.compare(0, groupname.size(), groupname) == 0 &&
|
|
||||||
iter->second.compare(groupname.size(), 2, ": ") == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
float calcAnimVelocity(const std::multimap<float, std::string>& keys,
|
|
||||||
NifOsg::KeyframeController *nonaccumctrl, const osg::Vec3f& accum, const std::string &groupname)
|
|
||||||
{
|
{
|
||||||
const std::string start = groupname+": start";
|
const std::string start = groupname+": start";
|
||||||
const std::string loopstart = groupname+": loop start";
|
const std::string loopstart = groupname+": loop start";
|
||||||
|
@ -179,7 +167,7 @@ namespace
|
||||||
// but the animation velocity calculation uses the second one.
|
// but the animation velocity calculation uses the second one.
|
||||||
// As result the animation velocity calculation is not correct, and this incorrect velocity must be replicated,
|
// As result the animation velocity calculation is not correct, and this incorrect velocity must be replicated,
|
||||||
// because otherwise the Creature's Speed (dagoth uthol) would not be sufficient to move fast enough.
|
// because otherwise the Creature's Speed (dagoth uthol) would not be sufficient to move fast enough.
|
||||||
NifOsg::TextKeyMap::const_reverse_iterator keyiter(keys.rbegin());
|
auto keyiter = keys.rbegin();
|
||||||
while(keyiter != keys.rend())
|
while(keyiter != keys.rend())
|
||||||
{
|
{
|
||||||
if(keyiter->second == start || keyiter->second == loopstart)
|
if(keyiter->second == start || keyiter->second == loopstart)
|
||||||
|
@ -553,7 +541,7 @@ namespace MWRender
|
||||||
|
|
||||||
ControllerMap mControllerMap[Animation::sNumBlendMasks];
|
ControllerMap mControllerMap[Animation::sNumBlendMasks];
|
||||||
|
|
||||||
const std::multimap<float, std::string>& getTextKeys() const;
|
const NifOsg::TextKeyMap& getTextKeys() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
@ -702,7 +690,7 @@ namespace MWRender
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::multimap<float, std::string> &Animation::AnimSource::getTextKeys() const
|
const NifOsg::TextKeyMap &Animation::AnimSource::getTextKeys() const
|
||||||
{
|
{
|
||||||
return mKeyframes->mTextKeys;
|
return mKeyframes->mTextKeys;
|
||||||
}
|
}
|
||||||
|
@ -825,7 +813,7 @@ namespace MWRender
|
||||||
for(;iter != mAnimSources.end();++iter)
|
for(;iter != mAnimSources.end();++iter)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
if(findGroupStart(keys, anim) != keys.end())
|
if (keys.hasGroupStart(anim))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,7 +826,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
|
|
||||||
NifOsg::TextKeyMap::const_iterator found = findGroupStart(keys, groupname);
|
const auto found = keys.findGroupStart(groupname);
|
||||||
if(found != keys.end())
|
if(found != keys.end())
|
||||||
return found->first;
|
return found->first;
|
||||||
}
|
}
|
||||||
|
@ -851,7 +839,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
|
|
||||||
for(NifOsg::TextKeyMap::const_iterator iterKey(keys.begin()); iterKey != keys.end(); ++iterKey)
|
for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
|
||||||
{
|
{
|
||||||
if(iterKey->second.compare(0, textKey.size(), textKey) == 0)
|
if(iterKey->second.compare(0, textKey.size(), textKey) == 0)
|
||||||
return iterKey->first;
|
return iterKey->first;
|
||||||
|
@ -861,8 +849,8 @@ namespace MWRender
|
||||||
return -1.f;
|
return -1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
void Animation::handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||||
const std::multimap<float, std::string>& map)
|
const NifOsg::TextKeyMap& map)
|
||||||
{
|
{
|
||||||
const std::string &evt = key->second;
|
const std::string &evt = key->second;
|
||||||
|
|
||||||
|
@ -939,7 +927,7 @@ namespace MWRender
|
||||||
|
|
||||||
if (state.mPlaying)
|
if (state.mPlaying)
|
||||||
{
|
{
|
||||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
|
auto textkey = textkeys.lowerBound(state.getTime());
|
||||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||||
{
|
{
|
||||||
handleTextKey(state, groupname, textkey, textkeys);
|
handleTextKey(state, groupname, textkey, textkeys);
|
||||||
|
@ -955,7 +943,7 @@ namespace MWRender
|
||||||
if(state.getTime() >= state.mLoopStopTime)
|
if(state.getTime() >= state.mLoopStopTime)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
|
auto textkey = textkeys.lowerBound(state.getTime());
|
||||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||||
{
|
{
|
||||||
handleTextKey(state, groupname, textkey, textkeys);
|
handleTextKey(state, groupname, textkey, textkeys);
|
||||||
|
@ -974,7 +962,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
|
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
|
||||||
// separate walkforward keys, and the last one is supposed to be used.
|
// separate walkforward keys, and the last one is supposed to be used.
|
||||||
NifOsg::TextKeyMap::const_reverse_iterator groupend(keys.rbegin());
|
auto groupend = keys.rbegin();
|
||||||
for(;groupend != keys.rend();++groupend)
|
for(;groupend != keys.rend();++groupend)
|
||||||
{
|
{
|
||||||
if(groupend->second.compare(0, groupname.size(), groupname) == 0 &&
|
if(groupend->second.compare(0, groupname.size(), groupname) == 0 &&
|
||||||
|
@ -983,7 +971,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string starttag = groupname+": "+start;
|
std::string starttag = groupname+": "+start;
|
||||||
NifOsg::TextKeyMap::const_reverse_iterator startkey(groupend);
|
auto startkey = groupend;
|
||||||
while(startkey != keys.rend() && startkey->second != starttag)
|
while(startkey != keys.rend() && startkey->second != starttag)
|
||||||
++startkey;
|
++startkey;
|
||||||
if(startkey == keys.rend() && start == "loop start")
|
if(startkey == keys.rend() && start == "loop start")
|
||||||
|
@ -997,7 +985,7 @@ namespace MWRender
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const std::string stoptag = groupname+": "+stop;
|
const std::string stoptag = groupname+": "+stop;
|
||||||
NifOsg::TextKeyMap::const_reverse_iterator stopkey(groupend);
|
auto stopkey = groupend;
|
||||||
while(stopkey != keys.rend()
|
while(stopkey != keys.rend()
|
||||||
// We have to ignore extra garbage at the end.
|
// We have to ignore extra garbage at the end.
|
||||||
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
|
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
|
||||||
|
@ -1030,7 +1018,7 @@ namespace MWRender
|
||||||
const std::string loopstarttag = groupname+": loop start";
|
const std::string loopstarttag = groupname+": loop start";
|
||||||
const std::string loopstoptag = groupname+": loop stop";
|
const std::string loopstoptag = groupname+": loop stop";
|
||||||
|
|
||||||
NifOsg::TextKeyMap::const_reverse_iterator key(groupend);
|
auto key = groupend;
|
||||||
for (; key != startkey && key != keys.rend(); ++key)
|
for (; key != startkey && key != keys.rend(); ++key)
|
||||||
{
|
{
|
||||||
if (key->first > state.getTime())
|
if (key->first > state.getTime())
|
||||||
|
@ -1064,7 +1052,7 @@ namespace MWRender
|
||||||
void Animation::resetActiveGroups()
|
void Animation::resetActiveGroups()
|
||||||
{
|
{
|
||||||
// remove all previous external controllers from the scene graph
|
// remove all previous external controllers from the scene graph
|
||||||
for (ControllerMap::iterator it = mActiveControllers.begin(); it != mActiveControllers.end(); ++it)
|
for (auto it = mActiveControllers.begin(); it != mActiveControllers.end(); ++it)
|
||||||
{
|
{
|
||||||
osg::Node* node = it->first;
|
osg::Node* node = it->first;
|
||||||
node->removeUpdateCallback(it->second);
|
node->removeUpdateCallback(it->second);
|
||||||
|
@ -1103,7 +1091,7 @@ namespace MWRender
|
||||||
osg::ref_ptr<osg::Node> node = getNodeMap().at(it->first); // this should not throw, we already checked for the node existing in addAnimSource
|
osg::ref_ptr<osg::Node> node = getNodeMap().at(it->first); // this should not throw, we already checked for the node existing in addAnimSource
|
||||||
|
|
||||||
node->addUpdateCallback(it->second);
|
node->addUpdateCallback(it->second);
|
||||||
mActiveControllers.insert(std::make_pair(node, it->second));
|
mActiveControllers.emplace_back(node, it->second);
|
||||||
|
|
||||||
if (blendMask == 0 && node == mAccumRoot)
|
if (blendMask == 0 && node == mAccumRoot)
|
||||||
{
|
{
|
||||||
|
@ -1116,7 +1104,7 @@ namespace MWRender
|
||||||
mResetAccumRootCallback->setAccumulate(mAccumulate);
|
mResetAccumRootCallback->setAccumulate(mAccumulate);
|
||||||
}
|
}
|
||||||
mAccumRoot->addUpdateCallback(mResetAccumRootCallback);
|
mAccumRoot->addUpdateCallback(mResetAccumRootCallback);
|
||||||
mActiveControllers.insert(std::make_pair(mAccumRoot, mResetAccumRootCallback));
|
mActiveControllers.emplace_back(mAccumRoot, mResetAccumRootCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1201,7 +1189,7 @@ namespace MWRender
|
||||||
for(;animsrc != mAnimSources.rend();++animsrc)
|
for(;animsrc != mAnimSources.rend();++animsrc)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
||||||
if(findGroupStart(keys, groupname) != keys.end())
|
if (keys.hasGroupStart(groupname))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(animsrc == mAnimSources.rend())
|
if(animsrc == mAnimSources.rend())
|
||||||
|
@ -1280,7 +1268,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
|
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
|
||||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.upper_bound(state.getTime()));
|
auto textkey = textkeys.upperBound(state.getTime());
|
||||||
|
|
||||||
float timepassed = duration * state.mSpeedMult;
|
float timepassed = duration * state.mSpeedMult;
|
||||||
while(state.mPlaying)
|
while(state.mPlaying)
|
||||||
|
@ -1316,7 +1304,7 @@ namespace MWRender
|
||||||
state.setTime(state.mLoopStartTime);
|
state.setTime(state.mLoopStartTime);
|
||||||
state.mPlaying = true;
|
state.mPlaying = true;
|
||||||
|
|
||||||
textkey = textkeys.lower_bound(state.getTime());
|
textkey = textkeys.lowerBound(state.getTime());
|
||||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||||
{
|
{
|
||||||
handleTextKey(state, stateiter->first, textkey, textkeys);
|
handleTextKey(state, stateiter->first, textkey, textkeys);
|
||||||
|
@ -1827,11 +1815,10 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
mHeadController = nullptr;
|
mHeadController = nullptr;
|
||||||
|
|
||||||
if (mPtr.getClass().isBipedal(mPtr))
|
|
||||||
{
|
|
||||||
NodeMap::const_iterator found = getNodeMap().find("bip01 head");
|
NodeMap::const_iterator found = getNodeMap().find("bip01 head");
|
||||||
if (found != getNodeMap().end())
|
if (found == getNodeMap().end())
|
||||||
{
|
return;
|
||||||
|
|
||||||
osg::MatrixTransform* node = found->second;
|
osg::MatrixTransform* node = found->second;
|
||||||
|
|
||||||
bool foundKeyframeCtrl = false;
|
bool foundKeyframeCtrl = false;
|
||||||
|
@ -1846,14 +1833,12 @@ namespace MWRender
|
||||||
cb = cb->getNestedCallback();
|
cb = cb->getNestedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundKeyframeCtrl)
|
if (!foundKeyframeCtrl)
|
||||||
{
|
return;
|
||||||
|
|
||||||
mHeadController = new RotateController(mObjectRoot.get());
|
mHeadController = new RotateController(mObjectRoot.get());
|
||||||
node->addUpdateCallback(mHeadController);
|
node->addUpdateCallback(mHeadController);
|
||||||
mActiveControllers.insert(std::make_pair(node, mHeadController));
|
mActiveControllers.emplace_back(node, mHeadController);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::setHeadPitch(float pitchRadians)
|
void Animation::setHeadPitch(float pitchRadians)
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
#include <components/sceneutil/controller.hpp>
|
#include <components/sceneutil/controller.hpp>
|
||||||
#include <components/sceneutil/util.hpp>
|
#include <components/sceneutil/util.hpp>
|
||||||
|
#include <components/nifosg/textkeymap.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -147,8 +150,8 @@ public:
|
||||||
class TextKeyListener
|
class TextKeyListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||||
const std::multimap<float, std::string>& map) = 0;
|
const NifOsg::TextKeyMap& map) = 0;
|
||||||
|
|
||||||
virtual ~TextKeyListener() = default;
|
virtual ~TextKeyListener() = default;
|
||||||
};
|
};
|
||||||
|
@ -246,8 +249,7 @@ protected:
|
||||||
|
|
||||||
// Keep track of controllers that we added to our scene graph.
|
// Keep track of controllers that we added to our scene graph.
|
||||||
// We may need to rebuild these controllers when the active animation groups / sources change.
|
// We may need to rebuild these controllers when the active animation groups / sources change.
|
||||||
typedef std::multimap<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback> > ControllerMap;
|
std::vector<std::pair<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback>>> mActiveControllers;
|
||||||
ControllerMap mActiveControllers;
|
|
||||||
|
|
||||||
std::shared_ptr<AnimationTime> mAnimationTimePtr[sNumBlendMasks];
|
std::shared_ptr<AnimationTime> mAnimationTimePtr[sNumBlendMasks];
|
||||||
|
|
||||||
|
@ -296,12 +298,12 @@ protected:
|
||||||
* the marker is not found, or if the markers are the same, it returns
|
* the marker is not found, or if the markers are the same, it returns
|
||||||
* false.
|
* false.
|
||||||
*/
|
*/
|
||||||
bool reset(AnimState &state, const std::multimap<float, std::string> &keys,
|
bool reset(AnimState &state, const NifOsg::TextKeyMap &keys,
|
||||||
const std::string &groupname, const std::string &start, const std::string &stop,
|
const std::string &groupname, const std::string &start, const std::string &stop,
|
||||||
float startpoint, bool loopfallback);
|
float startpoint, bool loopfallback);
|
||||||
|
|
||||||
void handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
void handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||||
const std::multimap<float, std::string>& map);
|
const NifOsg::TextKeyMap& map);
|
||||||
|
|
||||||
/** Sets the root model of the object.
|
/** Sets the root model of the object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -956,7 +956,7 @@ void NpcAnimation::addControllers()
|
||||||
osg::MatrixTransform* node = found->second.get();
|
osg::MatrixTransform* node = found->second.get();
|
||||||
mFirstPersonNeckController = new NeckController(mObjectRoot.get());
|
mFirstPersonNeckController = new NeckController(mObjectRoot.get());
|
||||||
node->addUpdateCallback(mFirstPersonNeckController);
|
node->addUpdateCallback(mFirstPersonNeckController);
|
||||||
mActiveControllers.emplace(node, mFirstPersonNeckController);
|
mActiveControllers.emplace_back(node, mFirstPersonNeckController);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mViewMode == VM_Normal)
|
else if (mViewMode == VM_Normal)
|
||||||
|
|
|
@ -231,7 +231,7 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength)
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeaponAnimation::addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
void WeaponAnimation::addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
||||||
std::multimap<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback> > &map, osg::Node* objectRoot)
|
std::vector<std::pair<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback>>> &map, osg::Node* objectRoot)
|
||||||
{
|
{
|
||||||
for (int i=0; i<2; ++i)
|
for (int i=0; i<2; ++i)
|
||||||
{
|
{
|
||||||
|
@ -243,7 +243,7 @@ void WeaponAnimation::addControllers(const std::map<std::string, osg::ref_ptr<os
|
||||||
osg::Node* node = found->second;
|
osg::Node* node = found->second;
|
||||||
mSpineControllers[i] = new RotateController(objectRoot);
|
mSpineControllers[i] = new RotateController(objectRoot);
|
||||||
node->addUpdateCallback(mSpineControllers[i]);
|
node->addUpdateCallback(mSpineControllers[i]);
|
||||||
map.insert(std::make_pair(node, mSpineControllers[i]));
|
map.emplace_back(node, mSpineControllers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWRender
|
||||||
|
|
||||||
/// Add WeaponAnimation-related controllers to \a nodes and store the added controllers in \a map.
|
/// Add WeaponAnimation-related controllers to \a nodes and store the added controllers in \a map.
|
||||||
void addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
void addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
||||||
std::multimap<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback> >& map, osg::Node* objectRoot);
|
std::vector<std::pair<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback>>>& map, osg::Node* objectRoot);
|
||||||
|
|
||||||
void deleteControllers();
|
void deleteControllers();
|
||||||
|
|
||||||
|
|
|
@ -496,13 +496,12 @@ namespace MWScript
|
||||||
if (!targetPtr.isEmpty() && targetPtr.getCellRef().getRefId() == testedTargetId)
|
if (!targetPtr.isEmpty() && targetPtr.getCellRef().getRefId() == testedTargetId)
|
||||||
targetsAreEqual = true;
|
targetsAreEqual = true;
|
||||||
}
|
}
|
||||||
else
|
else if (testedTargetId == "player") // Currently the player ID is hardcoded
|
||||||
{
|
{
|
||||||
bool turningToPlayer = creatureStats.isTurningToPlayer();
|
MWBase::MechanicsManager* mechMgr = MWBase::Environment::get().getMechanicsManager();
|
||||||
bool greeting = creatureStats.getGreetingState() == MWMechanics::Greet_InProgress;
|
bool greeting = mechMgr->getGreetingState(actor) == MWMechanics::Greet_InProgress;
|
||||||
bool sayActive = MWBase::Environment::get().getSoundManager()->sayActive(actor);
|
bool sayActive = MWBase::Environment::get().getSoundManager()->sayActive(actor);
|
||||||
if (turningToPlayer || (greeting && sayActive))
|
targetsAreEqual = (greeting && sayActive) || mechMgr->isTurningToPlayer(actor);
|
||||||
targetsAreEqual = (testedTargetId == "player"); // Currently the player ID is hardcoded
|
|
||||||
}
|
}
|
||||||
runtime.push(int(targetsAreEqual));
|
runtime.push(int(targetsAreEqual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,5 +464,20 @@ op 0x200030d: RepairedOnMe, explicit
|
||||||
op 0x200030e: TestCells
|
op 0x200030e: TestCells
|
||||||
op 0x200030f: TestInteriorCells
|
op 0x200030f: TestInteriorCells
|
||||||
op 0x2000310: ToggleRecastMesh
|
op 0x2000310: ToggleRecastMesh
|
||||||
|
op 0x2000311: MenuMode
|
||||||
|
op 0x2000312: Random
|
||||||
|
op 0x2000313: ScriptRunning
|
||||||
|
op 0x2000314: StartScript
|
||||||
|
op 0x2000315: StopScript
|
||||||
|
op 0x2000316: GetSecondsPassed
|
||||||
|
op 0x2000317: Enable
|
||||||
|
op 0x2000318: Disable
|
||||||
|
op 0x2000319: GetDisabled
|
||||||
|
op 0x200031a: Enable, explicit
|
||||||
|
op 0x200031b: Disable, explicit
|
||||||
|
op 0x200031c: GetDisabled, explicit
|
||||||
|
op 0x200031d: StartScript, explicit
|
||||||
|
op 0x200031e: GetDistance
|
||||||
|
op 0x200031f: GetDistance, explicit
|
||||||
|
|
||||||
opcodes 0x2000311-0x3ffffff unused
|
opcodes 0x2000320-0x3ffffff unused
|
||||||
|
|
|
@ -315,20 +315,6 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterpreterContext::menuMode()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Start of tes3mp change (major)
|
|
||||||
|
|
||||||
Being in a menu should not pause scripts in multiplayer, so always return false
|
|
||||||
*/
|
|
||||||
//return MWBase::Environment::get().getWindowManager()->isGuiMode();
|
|
||||||
return false;
|
|
||||||
/*
|
|
||||||
End of tes3mp change (major)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int InterpreterContext::getGlobalShort (const std::string& name) const
|
int InterpreterContext::getGlobalShort (const std::string& name) const
|
||||||
{
|
{
|
||||||
return MWBase::Environment::get().getWorld()->getGlobalInt (name);
|
return MWBase::Environment::get().getWorld()->getGlobalInt (name);
|
||||||
|
@ -627,58 +613,6 @@ namespace MWScript
|
||||||
return MWBase::Environment::get().getWorld()->getCellName();
|
return MWBase::Environment::get().getWorld()->getCellName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterpreterContext::isScriptRunning (const std::string& name) const
|
|
||||||
{
|
|
||||||
return MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::startScript (const std::string& name, const std::string& targetId)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr target;
|
|
||||||
if (targetId.empty())
|
|
||||||
target = getReference(false);
|
|
||||||
else
|
|
||||||
target = getReferenceImp(targetId);
|
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::stopScript (const std::string& name)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().removeScript (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
float InterpreterContext::getDistance (const std::string& name, const std::string& id) const
|
|
||||||
{
|
|
||||||
// NOTE: id may be empty, indicating an implicit reference
|
|
||||||
|
|
||||||
MWWorld::Ptr ref2 = getReferenceImp(id);
|
|
||||||
|
|
||||||
if (ref2.getContainerStore()) // is the object contained?
|
|
||||||
{
|
|
||||||
MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(ref2);
|
|
||||||
|
|
||||||
if (!container.isEmpty())
|
|
||||||
ref2 = container;
|
|
||||||
else
|
|
||||||
throw std::runtime_error("failed to find container ptr");
|
|
||||||
}
|
|
||||||
|
|
||||||
const MWWorld::Ptr ref = MWBase::Environment::get().getWorld()->getPtr(name, false);
|
|
||||||
|
|
||||||
// If the objects are in different worldspaces, return a large value (just like vanilla)
|
|
||||||
if (!ref.isInCell() || !ref2.isInCell() || ref.getCell()->getCell()->getCellId().mWorldspace != ref2.getCell()->getCell()->getCellId().mWorldspace)
|
|
||||||
return std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
double diff[3];
|
|
||||||
|
|
||||||
const float* const pos1 = ref.getRefData().getPosition().pos;
|
|
||||||
const float* const pos2 = ref2.getRefData().getPosition().pos;
|
|
||||||
for (int i=0; i<3; ++i)
|
|
||||||
diff[i] = pos1[i] - pos2[i];
|
|
||||||
|
|
||||||
return static_cast<float>(std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor)
|
void InterpreterContext::executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor)
|
||||||
{
|
{
|
||||||
std::shared_ptr<MWWorld::Action> action = (ptr.getClass().activate(ptr, actor));
|
std::shared_ptr<MWWorld::Action> action = (ptr.getClass().activate(ptr, actor));
|
||||||
|
@ -689,101 +623,6 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float InterpreterContext::getSecondsPassed() const
|
|
||||||
{
|
|
||||||
return MWBase::Environment::get().getFrameDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InterpreterContext::isDisabled (const std::string& id) const
|
|
||||||
{
|
|
||||||
const MWWorld::Ptr ref = getReferenceImp (id, false);
|
|
||||||
return !ref.getRefData().isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::enable (const std::string& id)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr ref = getReferenceImp (id, false);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp addition
|
|
||||||
|
|
||||||
Send an ID_OBJECT_STATE packet whenever an object is enabled, as long as
|
|
||||||
the player is logged in on the server, the object is still disabled, and our last
|
|
||||||
packet regarding its state did not already attempt to enable it (to prevent
|
|
||||||
packet spam)
|
|
||||||
*/
|
|
||||||
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
|
|
||||||
{
|
|
||||||
if (ref.isInCell() && !ref.getRefData().isEnabled() &&
|
|
||||||
ref.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Enabled)
|
|
||||||
{
|
|
||||||
ref.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Enabled);
|
|
||||||
|
|
||||||
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
||||||
objectList->reset();
|
|
||||||
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(getContextType());
|
|
||||||
objectList->addObjectState(ref, true);
|
|
||||||
objectList->sendObjectState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
End of tes3mp addition
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp change (major)
|
|
||||||
|
|
||||||
Disable unilateral state enabling on this client and expect the server's reply to our
|
|
||||||
packet to do it instead
|
|
||||||
*/
|
|
||||||
//MWBase::Environment::get().getWorld()->enable (ref);
|
|
||||||
/*
|
|
||||||
End of tes3mp change (major)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterContext::disable (const std::string& id)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr ref = getReferenceImp (id, false);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp addition
|
|
||||||
|
|
||||||
Send an ID_OBJECT_STATE packet whenever an object should be disabled, as long as
|
|
||||||
the player is logged in on the server, the object is still enabled, and our last
|
|
||||||
packet regarding its state did not already attempt to disable it (to prevent
|
|
||||||
packet spam)
|
|
||||||
*/
|
|
||||||
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
|
|
||||||
{
|
|
||||||
if (ref.isInCell() && ref.getRefData().isEnabled() &&
|
|
||||||
ref.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Disabled)
|
|
||||||
{
|
|
||||||
ref.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Disabled);
|
|
||||||
|
|
||||||
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
||||||
objectList->reset();
|
|
||||||
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(getContextType());
|
|
||||||
objectList->addObjectState(ref, false);
|
|
||||||
objectList->sendObjectState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
End of tes3mp addition
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp change (major)
|
|
||||||
|
|
||||||
Disable unilateral state disabling on this client and expect the server's reply to our
|
|
||||||
packet to do it instead
|
|
||||||
*/
|
|
||||||
//MWBase::Environment::get().getWorld()->disable (ref);
|
|
||||||
/*
|
|
||||||
End of tes3mp change (major)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int InterpreterContext::getMemberShort (const std::string& id, const std::string& name,
|
int InterpreterContext::getMemberShort (const std::string& id, const std::string& name,
|
||||||
bool global) const
|
bool global) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -102,8 +102,6 @@ namespace MWScript
|
||||||
virtual void report (const std::string& message);
|
virtual void report (const std::string& message);
|
||||||
///< By default, do nothing.
|
///< By default, do nothing.
|
||||||
|
|
||||||
virtual bool menuMode();
|
|
||||||
|
|
||||||
virtual int getGlobalShort (const std::string& name) const;
|
virtual int getGlobalShort (const std::string& name) const;
|
||||||
|
|
||||||
virtual int getGlobalLong (const std::string& name) const;
|
virtual int getGlobalLong (const std::string& name) const;
|
||||||
|
@ -146,26 +144,9 @@ namespace MWScript
|
||||||
|
|
||||||
virtual std::string getCurrentCellName() const;
|
virtual std::string getCurrentCellName() const;
|
||||||
|
|
||||||
virtual bool isScriptRunning (const std::string& name) const;
|
|
||||||
|
|
||||||
virtual void startScript (const std::string& name, const std::string& targetId = "");
|
|
||||||
|
|
||||||
virtual void stopScript (const std::string& name);
|
|
||||||
|
|
||||||
virtual float getDistance (const std::string& name, const std::string& id = "") const;
|
|
||||||
///< @note if \a id is empty, assumes an implicit reference
|
|
||||||
|
|
||||||
void executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor);
|
void executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor);
|
||||||
///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled.
|
///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled.
|
||||||
|
|
||||||
virtual float getSecondsPassed() const;
|
|
||||||
|
|
||||||
virtual bool isDisabled (const std::string& id = "") const;
|
|
||||||
|
|
||||||
virtual void enable (const std::string& id = "");
|
|
||||||
|
|
||||||
virtual void disable (const std::string& id = "");
|
|
||||||
|
|
||||||
virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const;
|
virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const;
|
||||||
|
|
||||||
virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const;
|
virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <components/interpreter/runtime.hpp>
|
#include <components/interpreter/runtime.hpp>
|
||||||
#include <components/interpreter/opcodes.hpp>
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/esm/loadmgef.hpp>
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
|
|
||||||
|
@ -92,6 +94,198 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
class OpMenuMode : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Being in a menu should not pause scripts in multiplayer, so always return false
|
||||||
|
*/
|
||||||
|
//runtime.push (MWBase::Environment::get().getWindowManager()->isGuiMode());
|
||||||
|
runtime.push(false);
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpRandom : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
Interpreter::Type_Integer limit = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
if (limit<0)
|
||||||
|
throw std::runtime_error (
|
||||||
|
"random: argument out of range (Don't be so negative!)");
|
||||||
|
|
||||||
|
runtime.push (static_cast<Interpreter::Type_Float>(::Misc::Rng::rollDice(limit))); // [o, limit)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpStartScript : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr target = R()(runtime, false);
|
||||||
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addScript (name, target);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpScriptRunning : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
runtime.push(MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpStopScript : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
MWBase::Environment::get().getScriptManager()->getGlobalScripts().removeScript (name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpGetSecondsPassed : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
runtime.push (MWBase::Environment::get().getFrameDuration());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpEnable : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Send an ID_OBJECT_STATE packet whenever an object is enabled, as long as
|
||||||
|
the player is logged in on the server, the object is still disabled, and our last
|
||||||
|
packet regarding its state did not already attempt to enable it (to prevent
|
||||||
|
packet spam)
|
||||||
|
*/
|
||||||
|
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
|
||||||
|
{
|
||||||
|
if (ptr.isInCell() && !ptr.getRefData().isEnabled() &&
|
||||||
|
ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Enabled)
|
||||||
|
{
|
||||||
|
ptr.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Enabled);
|
||||||
|
|
||||||
|
mwmp::ObjectList* objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
||||||
|
objectList->reset();
|
||||||
|
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
|
||||||
|
objectList->addObjectState(ptr, true);
|
||||||
|
objectList->sendObjectState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Disable unilateral state enabling on this client and expect the server's reply to our
|
||||||
|
packet to do it instead
|
||||||
|
*/
|
||||||
|
//MWBase::Environment::get().getWorld()->enable (ptr);
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpDisable : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Send an ID_OBJECT_STATE packet whenever an object should be disabled, as long as
|
||||||
|
the player is logged in on the server, the object is still enabled, and our last
|
||||||
|
packet regarding its state did not already attempt to disable it (to prevent
|
||||||
|
packet spam)
|
||||||
|
*/
|
||||||
|
if (mwmp::Main::get().getLocalPlayer()->isLoggedIn())
|
||||||
|
{
|
||||||
|
if (ptr.isInCell() && ptr.getRefData().isEnabled() &&
|
||||||
|
ptr.getRefData().getLastCommunicatedState() != MWWorld::RefData::StateCommunication::Disabled)
|
||||||
|
{
|
||||||
|
ptr.getRefData().setLastCommunicatedState(MWWorld::RefData::StateCommunication::Disabled);
|
||||||
|
|
||||||
|
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
||||||
|
objectList->reset();
|
||||||
|
objectList->packetOrigin = ScriptController::getPacketOriginFromContextType(runtime.getContext().getContextType());
|
||||||
|
objectList->addObjectState(ptr, false);
|
||||||
|
objectList->sendObjectState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
Disable unilateral state disabling on this client and expect the server's reply to our
|
||||||
|
packet to do it instead
|
||||||
|
*/
|
||||||
|
//MWBase::Environment::get().getWorld()->disable (ptr);
|
||||||
|
/*
|
||||||
|
End of tes3mp change (major)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpGetDisabled : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
runtime.push (!ptr.getRefData().isEnabled());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class OpPlayBink : public Interpreter::Opcode0
|
class OpPlayBink : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1575,6 +1769,19 @@ namespace MWScript
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeMenuMode, new OpMenuMode);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeRandom, new OpRandom);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeScriptRunning, new OpScriptRunning);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeStartScript, new OpStartScript<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeStartScriptExplicit, new OpStartScript<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeStopScript, new OpStopScript);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetSecondsPassed, new OpGetSecondsPassed);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeEnable, new OpEnable<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeEnableExplicit, new OpEnable<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeDisable, new OpDisable<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeDisableExplicit, new OpDisable<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetDisabled, new OpGetDisabled<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetDisabledExplicit, new OpGetDisabled<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
|
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeOnActivate, new OpOnActivate<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeOnActivate, new OpOnActivate<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeOnActivateExplicit, new OpOnActivate<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeOnActivateExplicit, new OpOnActivate<ExplicitRef>);
|
||||||
|
|
|
@ -56,6 +56,63 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpGetDistance : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr from = R()(runtime);
|
||||||
|
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
if (from.getContainerStore()) // is the object contained?
|
||||||
|
{
|
||||||
|
MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(from);
|
||||||
|
|
||||||
|
if (!container.isEmpty())
|
||||||
|
from = container;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string error = "Failed to find the container of object '" + from.getCellRef().getRefId() + "'";
|
||||||
|
runtime.getContext().report(error);
|
||||||
|
Log(Debug::Error) << error;
|
||||||
|
runtime.push(0.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MWWorld::Ptr to = MWBase::Environment::get().getWorld()->searchPtr(name, false);
|
||||||
|
if (to.isEmpty())
|
||||||
|
{
|
||||||
|
std::string error = "Failed to find an instance of object '" + name + "'";
|
||||||
|
runtime.getContext().report(error);
|
||||||
|
Log(Debug::Error) << error;
|
||||||
|
runtime.push(0.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float distance;
|
||||||
|
// If the objects are in different worldspaces, return a large value (just like vanilla)
|
||||||
|
if (!to.isInCell() || !from.isInCell() || to.getCell()->getCell()->getCellId().mWorldspace != from.getCell()->getCell()->getCellId().mWorldspace)
|
||||||
|
distance = std::numeric_limits<float>::max();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double diff[3];
|
||||||
|
|
||||||
|
const float* const pos1 = to.getRefData().getPosition().pos;
|
||||||
|
const float* const pos2 = from.getRefData().getPosition().pos;
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
diff[i] = pos1[i] - pos2[i];
|
||||||
|
|
||||||
|
distance = static_cast<float>(std::sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.push(distance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class R>
|
template<class R>
|
||||||
class OpSetScale : public Interpreter::Opcode0
|
class OpSetScale : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
|
@ -902,6 +959,8 @@ namespace MWScript
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
interpreter.installSegment5(Compiler::Transformation::opcodeGetDistance, new OpGetDistance<ImplicitRef>);
|
||||||
|
interpreter.installSegment5(Compiler::Transformation::opcodeGetDistanceExplicit, new OpGetDistance<ExplicitRef>);
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeSetScale,new OpSetScale<ImplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeSetScale,new OpSetScale<ImplicitRef>);
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeSetScaleExplicit,new OpSetScale<ExplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeSetScaleExplicit,new OpSetScale<ExplicitRef>);
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeSetAngle,new OpSetAngle<ImplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeSetAngle,new OpSetAngle<ImplicitRef>);
|
||||||
|
|
|
@ -240,12 +240,8 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
|
|
||||||
ESM::ESMWriter writer;
|
ESM::ESMWriter writer;
|
||||||
|
|
||||||
const std::vector<std::string>& current =
|
for (const std::string& contentFile : MWBase::Environment::get().getWorld()->getContentFiles())
|
||||||
MWBase::Environment::get().getWorld()->getContentFiles();
|
writer.addMaster(contentFile, 0); // not using the size information anyway -> use value of 0
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
|
|
||||||
++iter)
|
|
||||||
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
|
|
||||||
|
|
||||||
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||||
|
|
||||||
|
@ -356,10 +352,10 @@ void MWState::StateManager::quickSave (std::string name)
|
||||||
|
|
||||||
if (currentCharacter)
|
if (currentCharacter)
|
||||||
{
|
{
|
||||||
for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it)
|
for (auto& save : *currentCharacter)
|
||||||
{
|
{
|
||||||
//Visiting slots allows the quicksave finder to find the oldest quicksave
|
//Visiting slots allows the quicksave finder to find the oldest quicksave
|
||||||
saveFinder.visitSave(&*it);
|
saveFinder.visitSave(&save);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,12 +366,10 @@ void MWState::StateManager::quickSave (std::string name)
|
||||||
|
|
||||||
void MWState::StateManager::loadGame(const std::string& filepath)
|
void MWState::StateManager::loadGame(const std::string& filepath)
|
||||||
{
|
{
|
||||||
for (CharacterIterator it = mCharacterManager.begin(); it != mCharacterManager.end(); ++it)
|
for (const auto& character : mCharacterManager)
|
||||||
{
|
{
|
||||||
const MWState::Character& character = *it;
|
for (const auto& slot : character)
|
||||||
for (MWState::Character::SlotIterator slotIt = character.begin(); slotIt != character.end(); ++slotIt)
|
|
||||||
{
|
{
|
||||||
const MWState::Slot& slot = *slotIt;
|
|
||||||
if (slot.mPath == boost::filesystem::path(filepath))
|
if (slot.mPath == boost::filesystem::path(filepath))
|
||||||
{
|
{
|
||||||
loadGame(&character, slot.mPath.string());
|
loadGame(&character, slot.mPath.string());
|
||||||
|
@ -650,13 +644,12 @@ bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const
|
||||||
{
|
{
|
||||||
const std::vector<std::string>& selectedContentFiles = MWBase::Environment::get().getWorld()->getContentFiles();
|
const std::vector<std::string>& selectedContentFiles = MWBase::Environment::get().getWorld()->getContentFiles();
|
||||||
bool notFound = false;
|
bool notFound = false;
|
||||||
for (std::vector<std::string>::const_iterator it = profile.mContentFiles.begin();
|
for (const std::string& contentFile : profile.mContentFiles)
|
||||||
it != profile.mContentFiles.end(); ++it)
|
|
||||||
{
|
{
|
||||||
if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), *it)
|
if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), contentFile)
|
||||||
== selectedContentFiles.end())
|
== selectedContentFiles.end())
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Warning: Saved game dependency " << *it << " is missing.";
|
Log(Debug::Warning) << "Warning: Saved game dependency " << contentFile << " is missing.";
|
||||||
notFound = true;
|
notFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -785,7 +785,10 @@ namespace MWWorld
|
||||||
Ptr ret = searchPtr(name, activeOnly);
|
Ptr ret = searchPtr(name, activeOnly);
|
||||||
if (!ret.isEmpty())
|
if (!ret.isEmpty())
|
||||||
return ret;
|
return ret;
|
||||||
throw std::runtime_error ("unknown ID: " + name);
|
std::string error = "failed to find an instance of object '" + name + "'";
|
||||||
|
if (activeOnly)
|
||||||
|
error += " in active cells";
|
||||||
|
throw std::runtime_error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr World::searchPtrViaActorId (int actorId)
|
Ptr World::searchPtrViaActorId (int actorId)
|
||||||
|
@ -4509,4 +4512,10 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
return mPhysics->isAreaOccupiedByOtherActor(position, radius, ignore);
|
return mPhysics->isAreaOccupiedByOtherActor(position, radius, ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
mNavigator->reportStats(frameNumber, stats);
|
||||||
|
mPhysics->reportStats(frameNumber, stats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Group;
|
class Group;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace osgViewer
|
namespace osgViewer
|
||||||
|
@ -920,6 +921,8 @@ namespace MWWorld
|
||||||
bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override;
|
bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override;
|
||||||
|
|
||||||
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const override;
|
bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const override;
|
||||||
|
|
||||||
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ add_component_dir (compiler
|
||||||
|
|
||||||
add_component_dir (interpreter
|
add_component_dir (interpreter
|
||||||
context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes
|
context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes
|
||||||
miscopcodes opcodes runtime scriptopcodes spatialopcodes types defines
|
miscopcodes opcodes runtime types defines
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (translation
|
add_component_dir (translation
|
||||||
|
@ -368,3 +368,7 @@ endif()
|
||||||
|
|
||||||
# Make the variable accessible for other subdirectories
|
# Make the variable accessible for other subdirectories
|
||||||
set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE)
|
set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE)
|
||||||
|
|
||||||
|
if (BULLET_USE_DOUBLES)
|
||||||
|
add_definitions(-DBT_USE_DOUBLE_PRECISION)
|
||||||
|
endif()
|
||||||
|
|
|
@ -372,9 +372,7 @@ namespace Compiler
|
||||||
keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
|
keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
|
||||||
keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
|
keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
|
||||||
keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
|
keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
|
||||||
keyword==Scanner::K_to || keyword==Scanner::K_startscript ||
|
keyword==Scanner::K_to)
|
||||||
keyword==Scanner::K_stopscript || keyword==Scanner::K_enable ||
|
|
||||||
keyword==Scanner::K_disable)
|
|
||||||
{
|
{
|
||||||
return parseName (loc.mLiteral, loc, scanner);
|
return parseName (loc.mLiteral, loc, scanner);
|
||||||
}
|
}
|
||||||
|
@ -385,53 +383,6 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (mRefOp && mNextOperand)
|
if (mRefOp && mNextOperand)
|
||||||
{
|
{
|
||||||
if (keyword==Scanner::K_getdisabled)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
|
||||||
mOperands.push_back ('l');
|
|
||||||
mExplicit.clear();
|
|
||||||
mRefOp = false;
|
|
||||||
|
|
||||||
std::vector<Interpreter::Type_Code> ignore;
|
|
||||||
parseArguments ("x", scanner, ignore);
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_getdistance)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
parseArguments ("c", scanner);
|
|
||||||
|
|
||||||
Generator::getDistance (mCode, mLiterals, mExplicit);
|
|
||||||
mOperands.push_back ('f');
|
|
||||||
mExplicit.clear();
|
|
||||||
mRefOp = false;
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_scriptrunning)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
parseArguments ("c", scanner);
|
|
||||||
|
|
||||||
Generator::scriptRunning (mCode);
|
|
||||||
mOperands.push_back ('l');
|
|
||||||
|
|
||||||
mExplicit.clear();
|
|
||||||
mRefOp = false;
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
|
@ -483,84 +434,6 @@ namespace Compiler
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_menumode)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
|
|
||||||
Generator::menuMode (mCode);
|
|
||||||
mOperands.push_back ('l');
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_random)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
parseArguments ("l", scanner);
|
|
||||||
|
|
||||||
Generator::random (mCode);
|
|
||||||
mOperands.push_back ('f');
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_scriptrunning)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
parseArguments ("c", scanner);
|
|
||||||
|
|
||||||
Generator::scriptRunning (mCode);
|
|
||||||
mOperands.push_back ('l');
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_getdistance)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
parseArguments ("c", scanner);
|
|
||||||
|
|
||||||
Generator::getDistance (mCode, mLiterals, "");
|
|
||||||
mOperands.push_back ('f');
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_getsecondspassed)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
|
|
||||||
Generator::getSecondsPassed (mCode);
|
|
||||||
mOperands.push_back ('f');
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (keyword==Scanner::K_getdisabled)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
|
|
||||||
mTokenLoc = loc;
|
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, "");
|
|
||||||
mOperands.push_back ('l');
|
|
||||||
|
|
||||||
std::vector<Interpreter::Type_Code> ignore;
|
|
||||||
parseArguments ("x", scanner, ignore);
|
|
||||||
|
|
||||||
mNextOperand = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
|
|
|
@ -241,6 +241,15 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
void registerExtensions (Extensions& extensions)
|
void registerExtensions (Extensions& extensions)
|
||||||
{
|
{
|
||||||
|
extensions.registerFunction ("menumode", 'l', "", opcodeMenuMode);
|
||||||
|
extensions.registerFunction ("random", 'f', "l", opcodeRandom);
|
||||||
|
extensions.registerFunction ("scriptrunning", 'l', "c", opcodeScriptRunning);
|
||||||
|
extensions.registerInstruction ("startscript", "c", opcodeStartScript, opcodeStartScriptExplicit);
|
||||||
|
extensions.registerInstruction ("stopscript", "c", opcodeStopScript);
|
||||||
|
extensions.registerFunction ("getsecondspassed", 'f', "", opcodeGetSecondsPassed);
|
||||||
|
extensions.registerInstruction ("enable", "", opcodeEnable, opcodeEnableExplicit);
|
||||||
|
extensions.registerInstruction ("disable", "", opcodeDisable, opcodeDisableExplicit);
|
||||||
|
extensions.registerFunction ("getdisabled", 'l', "x", opcodeGetDisabled, opcodeGetDisabledExplicit);
|
||||||
extensions.registerFunction ("xbox", 'l', "", opcodeXBox);
|
extensions.registerFunction ("xbox", 'l', "", opcodeXBox);
|
||||||
extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate, opcodeOnActivateExplicit);
|
extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate, opcodeOnActivateExplicit);
|
||||||
extensions.registerInstruction ("activate", "x", opcodeActivate, opcodeActivateExplicit);
|
extensions.registerInstruction ("activate", "x", opcodeActivate, opcodeActivateExplicit);
|
||||||
|
@ -533,6 +542,7 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
void registerExtensions (Extensions& extensions)
|
void registerExtensions (Extensions& extensions)
|
||||||
{
|
{
|
||||||
|
extensions.registerFunction("getdistance",'f',"c",opcodeGetDistance,opcodeGetDistanceExplicit);
|
||||||
extensions.registerInstruction("setscale","f",opcodeSetScale,opcodeSetScaleExplicit);
|
extensions.registerInstruction("setscale","f",opcodeSetScale,opcodeSetScaleExplicit);
|
||||||
extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit);
|
extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit);
|
||||||
extensions.registerInstruction("setangle","cf",opcodeSetAngle,opcodeSetAngleExplicit);
|
extensions.registerInstruction("setangle","cf",opcodeSetAngle,opcodeSetAngleExplicit);
|
||||||
|
|
|
@ -222,11 +222,6 @@ namespace
|
||||||
code.push_back (Compiler::Generator::segment5 (37));
|
code.push_back (Compiler::Generator::segment5 (37));
|
||||||
}
|
}
|
||||||
|
|
||||||
void opMenuMode (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (38));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opStoreGlobalShort (Compiler::Generator::CodeContainer& code)
|
void opStoreGlobalShort (Compiler::Generator::CodeContainer& code)
|
||||||
{
|
{
|
||||||
code.push_back (Compiler::Generator::segment5 (39));
|
code.push_back (Compiler::Generator::segment5 (39));
|
||||||
|
@ -286,71 +281,6 @@ namespace
|
||||||
{
|
{
|
||||||
code.push_back (Compiler::Generator::segment5 (global ? 70 : 64));
|
code.push_back (Compiler::Generator::segment5 (global ? 70 : 64));
|
||||||
}
|
}
|
||||||
|
|
||||||
void opRandom (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (45));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opScriptRunning (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (46));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opStartScript (Compiler::Generator::CodeContainer& code, bool targeted)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (targeted ? 71 : 47));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opStopScript (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (48));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opGetDistance (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (49));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opGetSecondsPassed (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (50));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opEnable (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (51));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opDisable (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (52));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opGetDisabled (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (53));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opEnableExplicit (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (54));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opDisableExplicit (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (55));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opGetDisabledExplicit (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (56));
|
|
||||||
}
|
|
||||||
|
|
||||||
void opGetDistanceExplicit (Compiler::Generator::CodeContainer& code)
|
|
||||||
{
|
|
||||||
code.push_back (Compiler::Generator::segment5 (57));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
|
@ -645,11 +575,6 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menuMode (CodeContainer& code)
|
|
||||||
{
|
|
||||||
opMenuMode (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
|
void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
|
||||||
const std::string& name, const CodeContainer& value, char valueType)
|
const std::string& name, const CodeContainer& value, char valueType)
|
||||||
{
|
{
|
||||||
|
@ -806,93 +731,5 @@ namespace Compiler
|
||||||
assert (0);
|
assert (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void random (CodeContainer& code)
|
|
||||||
{
|
|
||||||
opRandom (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scriptRunning (CodeContainer& code)
|
|
||||||
{
|
|
||||||
opScriptRunning (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void startScript (CodeContainer& code, Literals& literals, const std::string& id)
|
|
||||||
{
|
|
||||||
if (id.empty())
|
|
||||||
opStartScript (code, false);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = literals.addString (id);
|
|
||||||
opPushInt (code, index);
|
|
||||||
opStartScript (code, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopScript (CodeContainer& code)
|
|
||||||
{
|
|
||||||
opStopScript (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void getDistance (CodeContainer& code, Literals& literals, const std::string& id)
|
|
||||||
{
|
|
||||||
if (id.empty())
|
|
||||||
{
|
|
||||||
opGetDistance (code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = literals.addString (id);
|
|
||||||
opPushInt (code, index);
|
|
||||||
opGetDistanceExplicit (code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void getSecondsPassed (CodeContainer& code)
|
|
||||||
{
|
|
||||||
opGetSecondsPassed (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void getDisabled (CodeContainer& code, Literals& literals, const std::string& id)
|
|
||||||
{
|
|
||||||
if (id.empty())
|
|
||||||
{
|
|
||||||
opGetDisabled (code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = literals.addString (id);
|
|
||||||
opPushInt (code, index);
|
|
||||||
opGetDisabledExplicit (code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void enable (CodeContainer& code, Literals& literals, const std::string& id)
|
|
||||||
{
|
|
||||||
if (id.empty())
|
|
||||||
{
|
|
||||||
opEnable (code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = literals.addString (id);
|
|
||||||
opPushInt (code, index);
|
|
||||||
opEnableExplicit (code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable (CodeContainer& code, Literals& literals, const std::string& id)
|
|
||||||
{
|
|
||||||
if (id.empty())
|
|
||||||
{
|
|
||||||
opDisable (code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = literals.addString (id);
|
|
||||||
opPushInt (code, index);
|
|
||||||
opDisableExplicit (code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,6 @@ namespace Compiler
|
||||||
|
|
||||||
void compare (CodeContainer& code, char op, char valueType1, char valueType2);
|
void compare (CodeContainer& code, char op, char valueType1, char valueType2);
|
||||||
|
|
||||||
void menuMode (CodeContainer& code);
|
|
||||||
|
|
||||||
void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
|
void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
|
||||||
const std::string& name, const CodeContainer& value, char valueType);
|
const std::string& name, const CodeContainer& value, char valueType);
|
||||||
|
|
||||||
|
@ -106,24 +104,6 @@ namespace Compiler
|
||||||
void fetchMember (CodeContainer& code, Literals& literals, char memberType,
|
void fetchMember (CodeContainer& code, Literals& literals, char memberType,
|
||||||
const std::string& name, const std::string& id, bool global);
|
const std::string& name, const std::string& id, bool global);
|
||||||
///< \param global Member of a global script instead of a script of a reference.
|
///< \param global Member of a global script instead of a script of a reference.
|
||||||
|
|
||||||
void random (CodeContainer& code);
|
|
||||||
|
|
||||||
void scriptRunning (CodeContainer& code);
|
|
||||||
|
|
||||||
void startScript (CodeContainer& code, Literals& literals, const std::string& id);
|
|
||||||
|
|
||||||
void stopScript (CodeContainer& code);
|
|
||||||
|
|
||||||
void getDistance (CodeContainer& code, Literals& literals, const std::string& id);
|
|
||||||
|
|
||||||
void getSecondsPassed (CodeContainer& code);
|
|
||||||
|
|
||||||
void getDisabled (CodeContainer& code, Literals& literals, const std::string& id);
|
|
||||||
|
|
||||||
void enable (CodeContainer& code, Literals& literals, const std::string& id);
|
|
||||||
|
|
||||||
void disable (CodeContainer& code, Literals& literals, const std::string& id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,35 +247,6 @@ namespace Compiler
|
||||||
|
|
||||||
if (mState==BeginState || mState==ExplicitState)
|
if (mState==BeginState || mState==ExplicitState)
|
||||||
{
|
{
|
||||||
switch (keyword)
|
|
||||||
{
|
|
||||||
case Scanner::K_enable:
|
|
||||||
|
|
||||||
Generator::enable (mCode, mLiterals, mExplicit);
|
|
||||||
mState = PotentialEndState;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Scanner::K_disable:
|
|
||||||
|
|
||||||
Generator::disable (mCode, mLiterals, mExplicit);
|
|
||||||
mState = PotentialEndState;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Scanner::K_startscript:
|
|
||||||
|
|
||||||
mExprParser.parseArguments ("c", scanner, mCode);
|
|
||||||
Generator::startScript (mCode, mLiterals, mExplicit);
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Scanner::K_stopscript:
|
|
||||||
|
|
||||||
mExprParser.parseArguments ("c", scanner, mCode);
|
|
||||||
Generator::stopScript (mCode);
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
{
|
{
|
||||||
|
@ -323,21 +294,6 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyword==Scanner::K_getdisabled || keyword==Scanner::K_getdistance)
|
|
||||||
{
|
|
||||||
if (mAllowExpression)
|
|
||||||
{
|
|
||||||
scanner.putbackKeyword (keyword, loc);
|
|
||||||
parseExpression (scanner, loc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
getErrorHandler().warning ("Unexpected naked expression", loc);
|
|
||||||
}
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
{
|
{
|
||||||
char returnType;
|
char returnType;
|
||||||
|
@ -416,13 +372,6 @@ namespace Compiler
|
||||||
mState = EndState;
|
mState = EndState;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Scanner::K_stopscript:
|
|
||||||
|
|
||||||
mExprParser.parseArguments ("c", scanner, mCode);
|
|
||||||
Generator::stopScript (mCode);
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Scanner::K_else:
|
case Scanner::K_else:
|
||||||
|
|
||||||
getErrorHandler().warning ("Stray else", loc);
|
getErrorHandler().warning ("Stray else", loc);
|
||||||
|
@ -484,19 +433,6 @@ namespace Compiler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAllowExpression)
|
|
||||||
{
|
|
||||||
if (keyword==Scanner::K_getsquareroot || keyword==Scanner::K_menumode ||
|
|
||||||
keyword==Scanner::K_random || keyword==Scanner::K_scriptrunning ||
|
|
||||||
keyword==Scanner::K_getsecondspassed)
|
|
||||||
{
|
|
||||||
scanner.putbackKeyword (keyword, loc);
|
|
||||||
parseExpression (scanner, loc);
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,19 @@ namespace Compiler
|
||||||
const int opcodeRepairedOnMe = 0x200030c;
|
const int opcodeRepairedOnMe = 0x200030c;
|
||||||
const int opcodeRepairedOnMeExplicit = 0x200030d;
|
const int opcodeRepairedOnMeExplicit = 0x200030d;
|
||||||
const int opcodeToggleRecastMesh = 0x2000310;
|
const int opcodeToggleRecastMesh = 0x2000310;
|
||||||
|
const int opcodeMenuMode = 0x2000311;
|
||||||
|
const int opcodeRandom = 0x2000312;
|
||||||
|
const int opcodeScriptRunning = 0x2000313;
|
||||||
|
const int opcodeStartScript = 0x2000314;
|
||||||
|
const int opcodeStopScript = 0x2000315;
|
||||||
|
const int opcodeGetSecondsPassed = 0x2000316;
|
||||||
|
const int opcodeEnable = 0x2000317;
|
||||||
|
const int opcodeDisable = 0x2000318;
|
||||||
|
const int opcodeGetDisabled = 0x2000319;
|
||||||
|
const int opcodeEnableExplicit = 0x200031a;
|
||||||
|
const int opcodeDisableExplicit = 0x200031b;
|
||||||
|
const int opcodeGetDisabledExplicit = 0x200031c;
|
||||||
|
const int opcodeStartScriptExplicit = 0x200031d;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Sky
|
namespace Sky
|
||||||
|
@ -513,6 +526,8 @@ namespace Compiler
|
||||||
const int opcodeMoveWorldExplicit = 0x2000209;
|
const int opcodeMoveWorldExplicit = 0x2000209;
|
||||||
const int opcodeResetActors = 0x20002f4;
|
const int opcodeResetActors = 0x20002f4;
|
||||||
const int opcodeFixme = 0x2000302;
|
const int opcodeFixme = 0x2000302;
|
||||||
|
const int opcodeGetDistance = 0x200031e;
|
||||||
|
const int opcodeGetDistanceExplicit = 0x200031f;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace User
|
namespace User
|
||||||
|
|
|
@ -266,12 +266,6 @@ namespace Compiler
|
||||||
"messagebox",
|
"messagebox",
|
||||||
"set", "to",
|
"set", "to",
|
||||||
"getsquareroot",
|
"getsquareroot",
|
||||||
"menumode",
|
|
||||||
"random",
|
|
||||||
"startscript", "stopscript", "scriptrunning",
|
|
||||||
"getdistance",
|
|
||||||
"getsecondspassed",
|
|
||||||
"enable", "disable", "getdisabled",
|
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -208,13 +208,7 @@ namespace Compiler
|
||||||
K_return,
|
K_return,
|
||||||
K_messagebox,
|
K_messagebox,
|
||||||
K_set, K_to,
|
K_set, K_to,
|
||||||
K_getsquareroot,
|
K_getsquareroot
|
||||||
K_menumode,
|
|
||||||
K_random,
|
|
||||||
K_startscript, K_stopscript, K_scriptrunning,
|
|
||||||
K_getdistance,
|
|
||||||
K_getsecondspassed,
|
|
||||||
K_enable, K_disable, K_getdisabled
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum special
|
enum special
|
||||||
|
|
|
@ -63,12 +63,7 @@ namespace Compiler
|
||||||
keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
|
keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
|
||||||
keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
|
keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
|
||||||
keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
|
keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
|
||||||
keyword==Scanner::K_to || keyword==Scanner::K_startscript ||
|
keyword==Scanner::K_to || keyword==Scanner::K_getsquareroot)
|
||||||
keyword==Scanner::K_stopscript || keyword==Scanner::K_enable ||
|
|
||||||
keyword==Scanner::K_disable || keyword==Scanner::K_getdisabled ||
|
|
||||||
keyword==Scanner::K_getdistance || keyword==Scanner::K_scriptrunning ||
|
|
||||||
keyword==Scanner::K_getsquareroot || keyword==Scanner::K_menumode ||
|
|
||||||
keyword==Scanner::K_random || keyword==Scanner::K_getsecondspassed)
|
|
||||||
{
|
{
|
||||||
return parseName (loc.mLiteral, loc, scanner);
|
return parseName (loc.mLiteral, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ namespace ESM
|
||||||
|
|
||||||
esm.writeHNT ("CAST", params.mCasterActorId);
|
esm.writeHNT ("CAST", params.mCasterActorId);
|
||||||
esm.writeHNString ("DISP", params.mDisplayName);
|
esm.writeHNString ("DISP", params.mDisplayName);
|
||||||
esm.writeHNT ("TIME", params.mTimeStamp);
|
|
||||||
|
|
||||||
for (std::vector<ActiveEffect>::const_iterator effectIt = params.mEffects.begin(); effectIt != params.mEffects.end(); ++effectIt)
|
for (std::vector<ActiveEffect>::const_iterator effectIt = params.mEffects.begin(); effectIt != params.mEffects.end(); ++effectIt)
|
||||||
{
|
{
|
||||||
|
@ -25,12 +24,15 @@ namespace ESM
|
||||||
esm.writeHNT ("ARG_", effectIt->mArg);
|
esm.writeHNT ("ARG_", effectIt->mArg);
|
||||||
esm.writeHNT ("MAGN", effectIt->mMagnitude);
|
esm.writeHNT ("MAGN", effectIt->mMagnitude);
|
||||||
esm.writeHNT ("DURA", effectIt->mDuration);
|
esm.writeHNT ("DURA", effectIt->mDuration);
|
||||||
|
esm.writeHNT ("LEFT", effectIt->mTimeLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSpells::load(ESMReader &esm)
|
void ActiveSpells::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
int format = esm.getFormat();
|
||||||
|
|
||||||
while (esm.isNextSub("ID__"))
|
while (esm.isNextSub("ID__"))
|
||||||
{
|
{
|
||||||
std::string spellId = esm.getHString();
|
std::string spellId = esm.getHString();
|
||||||
|
@ -38,7 +40,10 @@ namespace ESM
|
||||||
ActiveSpellParams params;
|
ActiveSpellParams params;
|
||||||
esm.getHNT (params.mCasterActorId, "CAST");
|
esm.getHNT (params.mCasterActorId, "CAST");
|
||||||
params.mDisplayName = esm.getHNString ("DISP");
|
params.mDisplayName = esm.getHNString ("DISP");
|
||||||
esm.getHNT (params.mTimeStamp, "TIME");
|
|
||||||
|
// spell casting timestamp, no longer used
|
||||||
|
if (esm.isNextSub("TIME"))
|
||||||
|
esm.skipHSub();
|
||||||
|
|
||||||
while (esm.isNextSub("MGEF"))
|
while (esm.isNextSub("MGEF"))
|
||||||
{
|
{
|
||||||
|
@ -48,6 +53,11 @@ namespace ESM
|
||||||
esm.getHNOT(effect.mArg, "ARG_");
|
esm.getHNOT(effect.mArg, "ARG_");
|
||||||
esm.getHNT (effect.mMagnitude, "MAGN");
|
esm.getHNT (effect.mMagnitude, "MAGN");
|
||||||
esm.getHNT (effect.mDuration, "DURA");
|
esm.getHNT (effect.mDuration, "DURA");
|
||||||
|
if (format < 9)
|
||||||
|
effect.mTimeLeft = effect.mDuration;
|
||||||
|
else
|
||||||
|
esm.getHNT (effect.mTimeLeft, "LEFT");
|
||||||
|
|
||||||
params.mEffects.push_back(effect);
|
params.mEffects.push_back(effect);
|
||||||
}
|
}
|
||||||
mSpells.insert(std::make_pair(spellId, params));
|
mSpells.insert(std::make_pair(spellId, params));
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace ESM
|
||||||
float mMagnitude;
|
float mMagnitude;
|
||||||
int mArg; // skill or attribute
|
int mArg; // skill or attribute
|
||||||
float mDuration;
|
float mDuration;
|
||||||
|
float mTimeLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
// format 0, saved games only
|
// format 0, saved games only
|
||||||
|
@ -29,7 +30,6 @@ namespace ESM
|
||||||
struct ActiveSpellParams
|
struct ActiveSpellParams
|
||||||
{
|
{
|
||||||
std::vector<ActiveEffect> mEffects;
|
std::vector<ActiveEffect> mEffects;
|
||||||
ESM::TimeStamp mTimeStamp;
|
|
||||||
std::string mDisplayName;
|
std::string mDisplayName;
|
||||||
int mCasterActorId;
|
int mCasterActorId;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
|
|
||||||
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
||||||
int ESM::SavedGame::sCurrentFormat = 8;
|
int ESM::SavedGame::sCurrentFormat = 9;
|
||||||
|
|
||||||
void ESM::SavedGame::load (ESMReader &esm)
|
void ESM::SavedGame::load (ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <WinReg.h>
|
#include <winreg.h>
|
||||||
|
|
||||||
#include <boost/locale.hpp>
|
#include <boost/locale.hpp>
|
||||||
namespace bconv = boost::locale::conv;
|
namespace bconv = boost::locale::conv;
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include <components/myguiplatform/myguitexture.hpp>
|
#include <components/myguiplatform/myguitexture.hpp>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
unsigned long utf8ToUnicode(const std::string& utf8)
|
unsigned long utf8ToUnicode(const std::string& utf8)
|
||||||
|
@ -147,15 +149,24 @@ namespace Gui
|
||||||
FontLoader::FontLoader(ToUTF8::FromType encoding, const VFS::Manager* vfs, const std::string& userDataPath)
|
FontLoader::FontLoader(ToUTF8::FromType encoding, const VFS::Manager* vfs, const std::string& userDataPath)
|
||||||
: mVFS(vfs)
|
: mVFS(vfs)
|
||||||
, mUserDataPath(userDataPath)
|
, mUserDataPath(userDataPath)
|
||||||
|
, mFontHeight(16)
|
||||||
{
|
{
|
||||||
if (encoding == ToUTF8::WINDOWS_1252)
|
if (encoding == ToUTF8::WINDOWS_1252)
|
||||||
mEncoding = ToUTF8::CP437;
|
mEncoding = ToUTF8::CP437;
|
||||||
else
|
else
|
||||||
mEncoding = encoding;
|
mEncoding = encoding;
|
||||||
|
|
||||||
|
int fontSize = Settings::Manager::getInt("font size", "GUI");
|
||||||
|
mFontHeight = std::min(std::max(12, fontSize), 20);
|
||||||
|
|
||||||
|
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
|
||||||
|
MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = MyGUI::newDelegate(this, &FontLoader::loadFontFromXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontLoader::~FontLoader()
|
FontLoader::~FontLoader()
|
||||||
{
|
{
|
||||||
|
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
|
||||||
|
|
||||||
for (std::vector<MyGUI::ITexture*>::iterator it = mTextures.begin(); it != mTextures.end(); ++it)
|
for (std::vector<MyGUI::ITexture*>::iterator it = mTextures.begin(); it != mTextures.end(); ++it)
|
||||||
delete *it;
|
delete *it;
|
||||||
mTextures.clear();
|
mTextures.clear();
|
||||||
|
@ -190,7 +201,7 @@ namespace Gui
|
||||||
{
|
{
|
||||||
size_t pos = name.find_last_of('.');
|
size_t pos = name.find_last_of('.');
|
||||||
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".fnt") == 0)
|
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".fnt") == 0)
|
||||||
loadFont(name, exportToFile);
|
loadBitmapFont(name, exportToFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -238,7 +249,7 @@ namespace Gui
|
||||||
float ascent;
|
float ascent;
|
||||||
} GlyphInfo;
|
} GlyphInfo;
|
||||||
|
|
||||||
void FontLoader::loadFont(const std::string &fileName, bool exportToFile)
|
void FontLoader::loadBitmapFont(const std::string &fileName, bool exportToFile)
|
||||||
{
|
{
|
||||||
Files::IStreamPtr file = mVFS->get(fileName);
|
Files::IStreamPtr file = mVFS->get(fileName);
|
||||||
|
|
||||||
|
@ -527,4 +538,96 @@ namespace Gui
|
||||||
MyGUI::ResourceManager::getInstance().addResource(bookFont);
|
MyGUI::ResourceManager::getInstance().addResource(bookFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FontLoader::loadFontFromXml(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version)
|
||||||
|
{
|
||||||
|
MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator();
|
||||||
|
bool createCopy = false;
|
||||||
|
while (resourceNode.next("Resource"))
|
||||||
|
{
|
||||||
|
std::string type, name;
|
||||||
|
resourceNode->findAttribute("type", type);
|
||||||
|
resourceNode->findAttribute("name", name);
|
||||||
|
|
||||||
|
if (name.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
|
||||||
|
{
|
||||||
|
createCopy = true;
|
||||||
|
|
||||||
|
// For TrueType fonts we should override Size and Resolution properties
|
||||||
|
// to allow to configure font size via config file, without need to edit XML files.
|
||||||
|
// Also we should take UI scaling factor in account.
|
||||||
|
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
|
||||||
|
resolution = std::min(960, std::max(48, resolution));
|
||||||
|
|
||||||
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
|
resolution *= uiScale;
|
||||||
|
|
||||||
|
MyGUI::xml::ElementPtr resolutionNode = resourceNode->createChild("Property");
|
||||||
|
resolutionNode->addAttribute("key", "Resolution");
|
||||||
|
resolutionNode->addAttribute("value", std::to_string(resolution));
|
||||||
|
|
||||||
|
MyGUI::xml::ElementPtr sizeNode = resourceNode->createChild("Property");
|
||||||
|
sizeNode->addAttribute("key", "Size");
|
||||||
|
sizeNode->addAttribute("value", std::to_string(mFontHeight));
|
||||||
|
}
|
||||||
|
else if (Misc::StringUtils::ciEqual(type, "ResourceSkin") ||
|
||||||
|
Misc::StringUtils::ciEqual(type, "AutoSizedResourceSkin"))
|
||||||
|
{
|
||||||
|
// We should adjust line height for MyGUI widgets depending on font size
|
||||||
|
MyGUI::xml::ElementPtr heightNode = resourceNode->createChild("Property");
|
||||||
|
heightNode->addAttribute("key", "HeightLine");
|
||||||
|
heightNode->addAttribute("value", std::to_string(mFontHeight+2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::ResourceManager::getInstance().loadFromXmlNode(_node, _file, _version);
|
||||||
|
|
||||||
|
if (createCopy)
|
||||||
|
{
|
||||||
|
MyGUI::xml::ElementPtr copy = _node->createCopy();
|
||||||
|
|
||||||
|
MyGUI::xml::ElementEnumerator copyFont = copy->getElementEnumerator();
|
||||||
|
while (copyFont.next("Resource"))
|
||||||
|
{
|
||||||
|
std::string type, name;
|
||||||
|
copyFont->findAttribute("type", type);
|
||||||
|
copyFont->findAttribute("name", name);
|
||||||
|
|
||||||
|
if (name.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
|
||||||
|
{
|
||||||
|
// Since the journal and books use the custom scaling factor depending on resolution,
|
||||||
|
// setup separate fonts with different Resolution to fit these windows.
|
||||||
|
// These fonts have an internal prefix.
|
||||||
|
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
|
||||||
|
resolution = std::min(960, std::max(48, resolution));
|
||||||
|
|
||||||
|
float currentX = Settings::Manager::getInt("resolution x", "Video");
|
||||||
|
float currentY = Settings::Manager::getInt("resolution y", "Video");
|
||||||
|
// TODO: read size from openmw_layout.xml somehow
|
||||||
|
float heightScale = (currentY / 520);
|
||||||
|
float widthScale = (currentX / 600);
|
||||||
|
float uiScale = std::min(widthScale, heightScale);
|
||||||
|
resolution *= uiScale;
|
||||||
|
|
||||||
|
MyGUI::xml::ElementPtr resolutionNode = copyFont->createChild("Property");
|
||||||
|
resolutionNode->addAttribute("key", "Resolution");
|
||||||
|
resolutionNode->addAttribute("value", std::to_string(resolution));
|
||||||
|
|
||||||
|
copyFont->setAttribute("name", "Journalbook " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::ResourceManager::getInstance().loadFromXmlNode(copy, _file, _version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int FontLoader::getFontHeight()
|
||||||
|
{
|
||||||
|
return mFontHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "boost/filesystem/operations.hpp"
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_XmlDocument.h>
|
||||||
|
#include <MyGUI_Version.h>
|
||||||
|
|
||||||
#include <components/myguiplatform/myguidatamanager.hpp>
|
#include <components/myguiplatform/myguidatamanager.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
@ -19,8 +22,6 @@ namespace MyGUI
|
||||||
|
|
||||||
namespace Gui
|
namespace Gui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/// @brief loads Morrowind's .fnt/.tex fonts for use with MyGUI and OSG
|
/// @brief loads Morrowind's .fnt/.tex fonts for use with MyGUI and OSG
|
||||||
/// @note The FontLoader needs to remain in scope as long as you want to use the loaded fonts.
|
/// @note The FontLoader needs to remain in scope as long as you want to use the loaded fonts.
|
||||||
class FontLoader
|
class FontLoader
|
||||||
|
@ -33,16 +34,21 @@ namespace Gui
|
||||||
void loadBitmapFonts (bool exportToFile);
|
void loadBitmapFonts (bool exportToFile);
|
||||||
void loadTrueTypeFonts ();
|
void loadTrueTypeFonts ();
|
||||||
|
|
||||||
|
void loadFontFromXml(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version);
|
||||||
|
|
||||||
|
int getFontHeight();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
const VFS::Manager* mVFS;
|
const VFS::Manager* mVFS;
|
||||||
std::string mUserDataPath;
|
std::string mUserDataPath;
|
||||||
|
int mFontHeight;
|
||||||
|
|
||||||
std::vector<MyGUI::ITexture*> mTextures;
|
std::vector<MyGUI::ITexture*> mTextures;
|
||||||
std::vector<MyGUI::ResourceManualFont*> mFonts;
|
std::vector<MyGUI::ResourceManualFont*> mFonts;
|
||||||
|
|
||||||
/// @param exportToFile export the converted font (Image and XML with glyph metrics) to files?
|
/// @param exportToFile export the converted font (Image and XML with glyph metrics) to files?
|
||||||
void loadFont (const std::string& fileName, bool exportToFile);
|
void loadBitmapFont (const std::string& fileName, bool exportToFile);
|
||||||
|
|
||||||
FontLoader(const FontLoader&);
|
FontLoader(const FontLoader&);
|
||||||
void operator=(const FontLoader&);
|
void operator=(const FontLoader&);
|
||||||
|
|
|
@ -51,8 +51,6 @@ namespace Interpreter
|
||||||
|
|
||||||
virtual void report (const std::string& message) = 0;
|
virtual void report (const std::string& message) = 0;
|
||||||
|
|
||||||
virtual bool menuMode() = 0;
|
|
||||||
|
|
||||||
virtual int getGlobalShort (const std::string& name) const = 0;
|
virtual int getGlobalShort (const std::string& name) const = 0;
|
||||||
|
|
||||||
virtual int getGlobalLong (const std::string& name) const = 0;
|
virtual int getGlobalLong (const std::string& name) const = 0;
|
||||||
|
@ -95,23 +93,6 @@ namespace Interpreter
|
||||||
|
|
||||||
virtual std::string getCurrentCellName() const = 0;
|
virtual std::string getCurrentCellName() const = 0;
|
||||||
|
|
||||||
virtual bool isScriptRunning (const std::string& name) const = 0;
|
|
||||||
|
|
||||||
virtual void startScript (const std::string& name, const std::string& targetId = "") = 0;
|
|
||||||
|
|
||||||
virtual void stopScript (const std::string& name) = 0;
|
|
||||||
|
|
||||||
virtual float getDistance (const std::string& name, const std::string& id = "") const
|
|
||||||
= 0;
|
|
||||||
|
|
||||||
virtual float getSecondsPassed() const = 0;
|
|
||||||
|
|
||||||
virtual bool isDisabled (const std::string& id = "") const = 0;
|
|
||||||
|
|
||||||
virtual void enable (const std::string& id = "") = 0;
|
|
||||||
|
|
||||||
virtual void disable (const std::string& id = "") = 0;
|
|
||||||
|
|
||||||
virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const = 0;
|
virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const = 0;
|
||||||
|
|
||||||
virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const = 0;
|
virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const = 0;
|
||||||
|
|
|
@ -96,27 +96,14 @@ op 34: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser than
|
||||||
op 35: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else
|
op 35: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else
|
||||||
op 36: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else
|
op 36: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else
|
||||||
op 37: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else
|
op 37: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else
|
||||||
op 38: push 1 if game is in menu mode, 0 else
|
opcode 38 unused
|
||||||
op 39: store stack[0] in global short stack[1] and pop twice
|
op 39: store stack[0] in global short stack[1] and pop twice
|
||||||
op 40: store stack[0] in global long stack[1] and pop twice
|
op 40: store stack[0] in global long stack[1] and pop twice
|
||||||
op 41: store stack[0] in global float stack[1] and pop twice
|
op 41: store stack[0] in global float stack[1] and pop twice
|
||||||
op 42: replace stack[0] with global short stack[0]
|
op 42: replace stack[0] with global short stack[0]
|
||||||
op 43: replace stack[0] with global long stack[0]
|
op 43: replace stack[0] with global long stack[0]
|
||||||
op 44: replace stack[0] with global float stack[0]
|
op 44: replace stack[0] with global float stack[0]
|
||||||
op 45: replace stack[0] with a random integer value in the range [0, stack[0]-1]
|
opcodes 45-57 unused
|
||||||
op 46: replace stack[0] with 1, if global script stack[0] is running, 0 else
|
|
||||||
op 47: start script stack[0] and pop
|
|
||||||
op 48: stop script stack[0] and pop
|
|
||||||
op 49: replace stack[0] with distance between implicit reference and a reference of ID stack[0]
|
|
||||||
op 50: push frame duration (float)
|
|
||||||
op 51: enable implicit reference
|
|
||||||
op 52: disable implicit reference
|
|
||||||
op 53: push 1, if implicit reference is disabled, 0 else
|
|
||||||
op 54: explicit reference = stack[0]; pop; enable explicit reference
|
|
||||||
op 55: explicit reference = stack[0]; pop; disable explicit reference
|
|
||||||
op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else
|
|
||||||
op 57: explicit reference = stack[0]; pop;
|
|
||||||
replace stack[0] with distance between explicit reference and a reference of ID stack[0]
|
|
||||||
op 58: report string literal index in stack[0];
|
op 58: report string literal index in stack[0];
|
||||||
additional arguments (if any) in stack[n]..stack[1];
|
additional arguments (if any) in stack[n]..stack[1];
|
||||||
n is determined according to the message string
|
n is determined according to the message string
|
||||||
|
@ -133,6 +120,5 @@ op 67: store stack[0] in member float stack[2] of global script with ID stack[1]
|
||||||
op 68: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
op 68: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||||
op 69: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
op 69: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||||
op 70: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
op 70: replace stack[0] with member short stack[1] of global script with ID stack[0]
|
||||||
op 71: explicit reference (target) = stack[0]; pop; start script stack[0] and pop
|
opcodes 71-33554431 unused
|
||||||
opcodes 72-33554431 unused
|
|
||||||
opcodes 33554432-67108863 reserved for extensions
|
opcodes 33554432-67108863 reserved for extensions
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include "mathopcodes.hpp"
|
#include "mathopcodes.hpp"
|
||||||
#include "controlopcodes.hpp"
|
#include "controlopcodes.hpp"
|
||||||
#include "miscopcodes.hpp"
|
#include "miscopcodes.hpp"
|
||||||
#include "scriptopcodes.hpp"
|
|
||||||
#include "spatialopcodes.hpp"
|
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
|
@ -97,25 +95,6 @@ namespace Interpreter
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
interpreter.installSegment3 (0, new OpMessageBox);
|
interpreter.installSegment3 (0, new OpMessageBox);
|
||||||
interpreter.installSegment5 (38, new OpMenuMode);
|
|
||||||
interpreter.installSegment5 (45, new OpRandom);
|
|
||||||
interpreter.installSegment5 (50, new OpGetSecondsPassed);
|
|
||||||
interpreter.installSegment5 (51, new OpEnable);
|
|
||||||
interpreter.installSegment5 (52, new OpDisable);
|
|
||||||
interpreter.installSegment5 (53, new OpGetDisabled);
|
|
||||||
interpreter.installSegment5 (54, new OpEnableExplicit);
|
|
||||||
interpreter.installSegment5 (55, new OpDisableExplicit);
|
|
||||||
interpreter.installSegment5 (56, new OpGetDisabledExplicit);
|
|
||||||
interpreter.installSegment5 (58, new OpReport);
|
interpreter.installSegment5 (58, new OpReport);
|
||||||
|
|
||||||
// script control
|
|
||||||
interpreter.installSegment5 (46, new OpScriptRunning);
|
|
||||||
interpreter.installSegment5 (47, new OpStartScript);
|
|
||||||
interpreter.installSegment5 (48, new OpStopScript);
|
|
||||||
interpreter.installSegment5 (71, new OpStartScriptExplicit);
|
|
||||||
|
|
||||||
// spacial
|
|
||||||
interpreter.installSegment5 (49, new OpGetDistance);
|
|
||||||
interpreter.installSegment5 (57, new OpGetDistanceExplicit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue