mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:53:52 +00:00
Merge branch 'master' into 'near_far_mode_in_launcher'
# Conflicts: # files/settings-default.cfg
This commit is contained in:
commit
66b5cf9f1d
363 changed files with 12324 additions and 7989 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -31,6 +31,7 @@ files/windows/*.aps
|
||||||
## qt-creator
|
## qt-creator
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
.vs
|
.vs
|
||||||
|
.vscode
|
||||||
|
|
||||||
## resources
|
## resources
|
||||||
data
|
data
|
||||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -2,14 +2,34 @@
|
||||||
------
|
------
|
||||||
|
|
||||||
Bug #1952: Incorrect particle lighting
|
Bug #1952: Incorrect particle lighting
|
||||||
|
Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs
|
||||||
Bug #3676: NiParticleColorModifier isn't applied properly
|
Bug #3676: NiParticleColorModifier isn't applied properly
|
||||||
|
Bug #3714: Savegame fails to load due to conflict between SpellState and MagicEffects
|
||||||
|
Bug #4021: Attributes and skills are not stored as floats
|
||||||
|
Bug #4623: Corprus implementation is incorrect
|
||||||
|
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 #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 #5403: Enchantment effect doesn't show on an enemy during death animation
|
||||||
|
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 #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
|
||||||
|
Bug #5451: Magic projectiles don't disappear with the caster
|
||||||
|
Bug #5452: Autowalk is being included in savegames
|
||||||
Feature #5362: Show the soul gems' trapped soul in count dialog
|
Feature #5362: Show the soul gems' trapped soul in count dialog
|
||||||
|
Feature #5445: Handle NiLines
|
||||||
|
|
||||||
0.46.0
|
0.46.0
|
||||||
------
|
------
|
||||||
|
@ -182,8 +202,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
|
||||||
|
@ -217,7 +237,6 @@
|
||||||
Bug #5264: "Damage Fatigue" Magic Effect Can Bring Fatigue below 0
|
Bug #5264: "Damage Fatigue" Magic Effect Can Bring Fatigue below 0
|
||||||
Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted
|
Bug #5269: Editor: Cell lighting in resaved cleaned content files is corrupted
|
||||||
Bug #5278: Console command Show doesn't fall back to global variable after local var not found
|
Bug #5278: Console command Show doesn't fall back to global variable after local var not found
|
||||||
Bug #5300: NPCs don't switch from torch to shield when starting combat
|
|
||||||
Bug #5308: World map copying makes save loading much slower
|
Bug #5308: World map copying makes save loading much slower
|
||||||
Bug #5313: Node properties of identical type are not applied in the correct order
|
Bug #5313: Node properties of identical type are not applied in the correct order
|
||||||
Bug #5326: Formatting issues in the settings.cfg
|
Bug #5326: Formatting issues in the settings.cfg
|
||||||
|
@ -282,7 +301,7 @@
|
||||||
Feature #5147: Show spell magicka cost in spell buying window
|
Feature #5147: Show spell magicka cost in spell buying window
|
||||||
Feature #5170: Editor: Land shape editing, land selection
|
Feature #5170: Editor: Land shape editing, land selection
|
||||||
Feature #5172: Editor: Delete instances/references with keypress in scene window
|
Feature #5172: Editor: Delete instances/references with keypress in scene window
|
||||||
Feature #5193: Weapon sheathing
|
Feature #5193: Shields sheathing
|
||||||
Feature #5201: Editor: Show tool outline in scene view, when using editmodes
|
Feature #5201: Editor: Show tool outline in scene view, when using editmodes
|
||||||
Feature #5219: Impelement TestCells console command
|
Feature #5219: Impelement TestCells console command
|
||||||
Feature #5224: Handle NiKeyframeController for NiTriShape
|
Feature #5224: Handle NiKeyframeController for NiTriShape
|
||||||
|
|
|
@ -13,21 +13,28 @@ The OpenMW team is proud to announce the release of version 0.47.0! Grab it from
|
||||||
Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes.
|
Check out the release video (***add link***) and the OpenMW-CS release video (***add link***) by the ***add flattering adjective*** Atahualpa, and see below for the full list of changes.
|
||||||
|
|
||||||
Known Issues:
|
Known Issues:
|
||||||
- There's currently no way to redirect the logging output to the command prompt on Windows Release builds -- this will be resolved in version 0.46.0
|
|
||||||
- To use generic Linux binaries, Qt4 and libpng12 must be installed on your system
|
- To use generic Linux binaries, Qt4 and libpng12 must be installed on your system
|
||||||
- On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings
|
- On macOS, launching OpenMW from OpenMW-CS requires OpenMW.app and OpenMW-CS.app to be siblings
|
||||||
|
|
||||||
New Features:
|
New Features:
|
||||||
- ?
|
- Dialogue to split item stacks now displays the name of the trapped soul for stacks of soul gems (#5362)
|
||||||
|
|
||||||
New Editor Features:
|
New Editor Features:
|
||||||
- ?
|
- ?
|
||||||
|
|
||||||
Bug Fixes:
|
Bug Fixes:
|
||||||
- ?
|
- NiParticleColorModifier in NIF files is now properly handled which solves issues regarding particle effects, e.g., smoke and fire (#1952, #3676)
|
||||||
|
- Targetting non-unique actors in scripts is now supported (#2311)
|
||||||
|
- Guards no longer ignore attacks of invisible players but rather initiate dialogue and flee if the player resists being arrested (#4774)
|
||||||
|
- Changing the dialogue window without closing it no longer clears the dialogue history in order to allow, e.g., emulation of three-way dialogue via ForceGreeting (#5358)
|
||||||
|
- Scripts which try to start a non-existent global script now skip that step and continue execution instead of breaking (#5364)
|
||||||
|
- Selecting already equipped spells or magic items via hotkey no longer triggers the equip sound to play (#5367)
|
||||||
|
- 'Scale' argument in levelled creature lists is now taken into account when spawning creatures from such lists (#5369)
|
||||||
|
- Morrowind legacy madness: Using a key on a trapped door/container now only disarms the trap if the door/container is locked (#5370)
|
||||||
|
|
||||||
Editor Bug Fixes:
|
Editor Bug Fixes:
|
||||||
- ?
|
- Verifier no longer checks for alleged 'race' entries in clothing body parts (#5400)
|
||||||
|
|
||||||
Miscellaneous:
|
Miscellaneous:
|
||||||
- ?
|
- Prevent save-game bloating by using an appropriate fog texture format (#5108)
|
||||||
|
- Ensure that 'Enchantment autocalc" flag is treated as flag in OpenMW-CS and in our esm tools (#5363)
|
28
CI/ActivateMSVC.ps1
Normal file
28
CI/ActivateMSVC.ps1
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
& "${env:COMSPEC}" /c ActivateMSVC.bat "&&" set | ForEach-Object {
|
||||||
|
if ($_.Contains("=")) {
|
||||||
|
$name, $value = $_ -split '=', 2
|
||||||
|
Set-Content env:\"$name" $value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$MissingTools = $false
|
||||||
|
$tools = "cl", "link", "rc", "mt"
|
||||||
|
$descriptions = "MSVC Compiler", "MSVC Linker", "MS Windows Resource Compiler", "MS Windows Manifest Tool"
|
||||||
|
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"
|
|
@ -25,7 +25,6 @@ ${ANALYZE} cmake \
|
||||||
-DBUILD_ESSIMPORTER=${BUILD_OPENMW_CS} \
|
-DBUILD_ESSIMPORTER=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_WIZARD=${BUILD_OPENMW_CS} \
|
-DBUILD_WIZARD=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_NIFTEST=${BUILD_OPENMW_CS} \
|
-DBUILD_NIFTEST=${BUILD_OPENMW_CS} \
|
||||||
-DBUILD_MYGUI_PLUGIN=${BUILD_OPENMW_CS} \
|
|
||||||
-DBUILD_UNITTESTS=1 \
|
-DBUILD_UNITTESTS=1 \
|
||||||
-DUSE_SYSTEM_TINYXML=1 \
|
-DUSE_SYSTEM_TINYXML=1 \
|
||||||
-DDESIRED_QT_VERSION=5 \
|
-DDESIRED_QT_VERSION=5 \
|
||||||
|
|
|
@ -1,25 +1,59 @@
|
||||||
#!/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; }
|
||||||
|
|
||||||
|
MISSINGPYTHON=0
|
||||||
|
if ! command -v python >/dev/null 2>&1; then
|
||||||
|
echo "Warning: Python is not on the path, automatic Qt installation impossible."
|
||||||
|
MISSINGPYTHON=1
|
||||||
|
elif ! python --version >/dev/null 2>&1; then
|
||||||
|
echo "Warning: Python is (probably) fake stub Python that comes bundled with newer versions of Windows, automatic Qt installation impossible."
|
||||||
|
echo "If you think you have Python installed, try changing the order of your PATH environment variable in Advanced System Settings."
|
||||||
|
MISSINGPYTHON=1
|
||||||
|
fi
|
||||||
|
|
||||||
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,10 +66,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="."
|
||||||
|
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
|
||||||
|
@ -44,7 +87,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
|
||||||
|
@ -56,6 +99,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 ;;
|
||||||
|
|
||||||
|
@ -71,11 +117,17 @@ 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 ;;
|
||||||
|
@ -83,14 +135,20 @@ while [ $# -gt 0 ]; do
|
||||||
t )
|
t )
|
||||||
TEST_FRAMEWORK=true ;;
|
TEST_FRAMEWORK=true ;;
|
||||||
|
|
||||||
|
i )
|
||||||
|
INSTALL_PREFIX=$(echo "$1" | sed 's;\\;/;g' | sed -E 's;/+;/;g')
|
||||||
|
shift ;;
|
||||||
|
|
||||||
h )
|
h )
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $0 [-cdehkpuvV]
|
Usage: $0 [-cdehkpuvVi]
|
||||||
Options:
|
Options:
|
||||||
-c <Release/Debug>
|
-c <Release/Debug>
|
||||||
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
|
||||||
|
@ -106,23 +164,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
|
||||||
|
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
|
||||||
|
@ -132,7 +200,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."
|
||||||
|
@ -145,8 +213,8 @@ run_cmd() {
|
||||||
shift
|
shift
|
||||||
|
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
eval $CMD $@ > output.log 2>&1
|
RET=0
|
||||||
RET=$?
|
eval $CMD $@ > output.log 2>&1 || RET=$?
|
||||||
|
|
||||||
if [ $RET -ne 0 ]; then
|
if [ $RET -ne 0 ]; then
|
||||||
if [ -z $APPVEYOR ]; then
|
if [ -z $APPVEYOR ]; then
|
||||||
|
@ -162,8 +230,9 @@ run_cmd() {
|
||||||
|
|
||||||
return $RET
|
return $RET
|
||||||
else
|
else
|
||||||
eval $CMD $@
|
RET=0
|
||||||
return $?
|
eval $CMD $@ || RET=$?
|
||||||
|
return $RET
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,15 +257,16 @@ download() {
|
||||||
printf " Downloading $FILE... "
|
printf " Downloading $FILE... "
|
||||||
|
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
curl --silent --retry 10 -kLy 5 -o $FILE $URL
|
RET=0
|
||||||
RET=$?
|
curl --silent --retry 10 -kLy 5 -o $FILE $URL || RET=$?
|
||||||
else
|
else
|
||||||
curl --retry 10 -kLy 5 -o $FILE $URL
|
RET=0
|
||||||
RET=$?
|
curl --retry 10 -kLy 5 -o $FILE $URL || RET=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $RET -ne 0 ]; then
|
if [ $RET -ne 0 ]; then
|
||||||
echo "Failed!"
|
echo "Failed!"
|
||||||
|
wrappedExit $RET
|
||||||
else
|
else
|
||||||
echo "Done."
|
echo "Done."
|
||||||
fi
|
fi
|
||||||
|
@ -257,6 +327,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"
|
||||||
|
@ -269,6 +340,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"
|
||||||
|
@ -281,6 +353,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"
|
||||||
|
@ -288,15 +361,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
|
||||||
|
|
||||||
|
@ -315,7 +381,7 @@ case $PLATFORM in
|
||||||
|
|
||||||
* )
|
* )
|
||||||
echo "Unknown platform $PLATFORM."
|
echo "Unknown platform $PLATFORM."
|
||||||
exit 1
|
wrappedExit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -342,9 +408,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
|
||||||
|
@ -354,7 +429,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
|
||||||
|
|
||||||
|
@ -362,6 +437,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}"
|
||||||
|
@ -386,45 +467,54 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bullet
|
# Bullet
|
||||||
download "Bullet 2.86" \
|
download "Bullet 2.89 (${BULLET_DBL_DISPLAY})" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-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.86-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
|
||||||
|
@ -449,7 +539,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
|
||||||
|
@ -487,10 +583,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
|
||||||
|
@ -526,15 +622,15 @@ fi
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# Bullet
|
# Bullet
|
||||||
printf "Bullet 2.86... "
|
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.86-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.86-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.
|
||||||
|
@ -542,21 +638,21 @@ printf "Bullet 2.86... "
|
||||||
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
|
||||||
|
@ -565,62 +661,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"
|
||||||
|
@ -629,17 +729,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
|
||||||
|
@ -651,21 +751,49 @@ 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
|
||||||
|
if [ $MISSINGPYTHON -ne 0 ]; then
|
||||||
|
echo "Can't be automatically installed without Python."
|
||||||
|
wrappedExit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd "$DEPS" > /dev/null
|
||||||
|
if ! [ -d 'aqt-venv' ]; then
|
||||||
|
echo " Creating Virtualenv for aqt..."
|
||||||
|
eval python -m venv aqt-venv $STRIP
|
||||||
|
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
|
rm -rf Qt
|
||||||
cp "${DEPS}/qt-5-install.qs" qt-install.qs
|
|
||||||
sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" qt-install.qs
|
mkdir Qt
|
||||||
sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs
|
cd Qt
|
||||||
printf -- "(Installation might take a while) "
|
|
||||||
"${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent
|
eval "${DEPS}/aqt-venv/${VENV_BIN_DIR}/aqt" install 5.15.0 windows desktop "win${BITS}_msvc${MSVC_REAL_YEAR}${SUFFIX}" $STRIP
|
||||||
mv qt-install.qs Qt/
|
|
||||||
echo Done.
|
|
||||||
printf " Cleaning up extraneous data... "
|
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}
|
rm -rf Qt/{aqtinstall.log,Tools}
|
||||||
|
|
||||||
|
echo Done.
|
||||||
fi
|
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" \
|
||||||
|
@ -688,7 +816,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.
|
||||||
|
@ -759,10 +887,8 @@ echo
|
||||||
cd $DEPS_INSTALL/..
|
cd $DEPS_INSTALL/..
|
||||||
echo
|
echo
|
||||||
echo "Setting up OpenMW build..."
|
echo "Setting up OpenMW build..."
|
||||||
add_cmake_opts -DBUILD_BSATOOL=no \
|
add_cmake_opts -DOPENMW_MP_BUILD=on
|
||||||
-DBUILD_ESMTOOL=no \
|
add_cmake_opts -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}"
|
||||||
-DBUILD_MYGUI_PLUGIN=no \
|
|
||||||
-DOPENMW_MP_BUILD=on
|
|
||||||
if [ ! -z $CI ]; then
|
if [ ! -z $CI ]; then
|
||||||
case $STEP in
|
case $STEP in
|
||||||
components )
|
components )
|
||||||
|
@ -801,14 +927,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
|
||||||
|
@ -817,10 +944,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..."
|
||||||
|
@ -831,13 +958,49 @@ fi
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
#fi
|
#fi
|
||||||
|
|
||||||
|
if [ -n "$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 -products '*' -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
|
||||||
echo "- cmake .. $CMAKE_OPTS"
|
echo "- cmake .. $CMAKE_OPTS"
|
||||||
fi
|
fi
|
||||||
run_cmd cmake .. $CMAKE_OPTS
|
RET=0
|
||||||
RET=$?
|
run_cmd cmake .. $CMAKE_OPTS || RET=$?
|
||||||
if [ -z $VERBOSE ]; then
|
if [ -z $VERBOSE ]; then
|
||||||
if [ $RET -eq 0 ]; then
|
if [ $RET -eq 0 ]; then
|
||||||
echo Done.
|
echo Done.
|
||||||
|
@ -845,4 +1008,38 @@ if [ -z $VERBOSE ]; then
|
||||||
echo Failed.
|
echo Failed.
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
exit $RET
|
if [ $RET -ne 0 ]; then
|
||||||
|
wrappedExit $RET
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Script completed successfully."
|
||||||
|
echo "You now have an OpenMW build system at $(unixPathAsWindows "$(pwd)")"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
wrappedExit $RET
|
||||||
|
|
|
@ -19,6 +19,5 @@ cmake \
|
||||||
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
||||||
-D DESIRED_QT_VERSION=5 \
|
-D DESIRED_QT_VERSION=5 \
|
||||||
-D BUILD_ESMTOOL=FALSE \
|
-D BUILD_ESMTOOL=FALSE \
|
||||||
-D BUILD_MYGUI_PLUGIN=FALSE \
|
|
||||||
-G"Unix Makefiles" \
|
-G"Unix Makefiles" \
|
||||||
..
|
..
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
git clone -b release-1.8.1 https://github.com/google/googletest.git
|
git clone -b release-1.10.0 https://github.com/google/googletest.git
|
||||||
cd googletest
|
cd googletest
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
|
@ -8,10 +8,10 @@ option(BUILD_ESSIMPORTER "Build ESS (Morrowind save game) importer" ON)
|
||||||
option(BUILD_BSATOOL "Build BSA extractor" ON)
|
option(BUILD_BSATOOL "Build BSA extractor" ON)
|
||||||
option(BUILD_ESMTOOL "Build ESM inspector" ON)
|
option(BUILD_ESMTOOL "Build ESM inspector" ON)
|
||||||
option(BUILD_NIFTEST "Build nif file tester" ON)
|
option(BUILD_NIFTEST "Build nif file tester" ON)
|
||||||
option(BUILD_MYGUI_PLUGIN "Build MyGUI plugin for OpenMW resources, to use with MyGUI tools" 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)
|
||||||
|
|
||||||
if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD)
|
||||||
set(USE_QT FALSE)
|
set(USE_QT FALSE)
|
||||||
|
@ -468,9 +468,6 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||||
IF(BUILD_WIZARD)
|
IF(BUILD_WIZARD)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" )
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" )
|
||||||
ENDIF(BUILD_WIZARD)
|
ENDIF(BUILD_WIZARD)
|
||||||
#if(BUILD_MYGUI_PLUGIN)
|
|
||||||
# INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" )
|
|
||||||
#ENDIF(BUILD_MYGUI_PLUGIN)
|
|
||||||
|
|
||||||
# Install licenses
|
# Install licenses
|
||||||
INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||||
|
@ -517,11 +514,6 @@ if(WIN32)
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug)
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug)
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||||
|
|
||||||
if(BUILD_MYGUI_PLUGIN)
|
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Debug/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION "." CONFIGURATIONS Debug)
|
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
|
||||||
ENDIF(BUILD_MYGUI_PLUGIN)
|
|
||||||
|
|
||||||
IF(DESIRED_QT_VERSION MATCHES 5)
|
IF(DESIRED_QT_VERSION MATCHES 5)
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/platforms" DESTINATION "." CONFIGURATIONS Debug)
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/platforms" DESTINATION "." CONFIGURATIONS Debug)
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Release/platforms" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Release/platforms" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||||
|
@ -913,4 +905,3 @@ if (DOXYGEN_FOUND)
|
||||||
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
|
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
|
||||||
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
|
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -183,19 +183,19 @@ int list(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
{
|
{
|
||||||
// List all files
|
// List all files
|
||||||
const Bsa::BSAFile::FileList &files = bsa.getList();
|
const Bsa::BSAFile::FileList &files = bsa.getList();
|
||||||
for(unsigned int i=0; i<files.size(); i++)
|
for (const auto& file : files)
|
||||||
{
|
{
|
||||||
if(info.longformat)
|
if(info.longformat)
|
||||||
{
|
{
|
||||||
// Long format
|
// Long format
|
||||||
std::ios::fmtflags f(std::cout.flags());
|
std::ios::fmtflags f(std::cout.flags());
|
||||||
std::cout << std::setw(50) << std::left << files[i].name;
|
std::cout << std::setw(50) << std::left << file.name;
|
||||||
std::cout << std::setw(8) << std::left << std::dec << files[i].fileSize;
|
std::cout << std::setw(8) << std::left << std::dec << file.fileSize;
|
||||||
std::cout << "@ 0x" << std::hex << files[i].offset << std::endl;
|
std::cout << "@ 0x" << std::hex << file.offset << std::endl;
|
||||||
std::cout.flags(f);
|
std::cout.flags(f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cout << files[i].name << std::endl;
|
std::cout << file.name << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -252,14 +252,9 @@ int extract(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
|
|
||||||
int extractAll(Bsa::BSAFile& bsa, Arguments& info)
|
int extractAll(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
{
|
{
|
||||||
// Get the list of files present in the archive
|
for (const auto &file : bsa.getList())
|
||||||
Bsa::BSAFile::FileList list = bsa.getList();
|
{
|
||||||
|
std::string extractPath(file.name);
|
||||||
// Iter on the list
|
|
||||||
for(Bsa::BSAFile::FileList::iterator it = list.begin(); it != list.end(); ++it) {
|
|
||||||
const char* archivePath = it->name;
|
|
||||||
|
|
||||||
std::string extractPath (archivePath);
|
|
||||||
replaceAll(extractPath, "\\", "/");
|
replaceAll(extractPath, "\\", "/");
|
||||||
|
|
||||||
// Get the target path (the path the file will be extracted to)
|
// Get the target path (the path the file will be extracted to)
|
||||||
|
@ -278,7 +273,7 @@ int extractAll(Bsa::BSAFile& bsa, Arguments& info)
|
||||||
|
|
||||||
// Get a stream for the file to extract
|
// Get a stream for the file to extract
|
||||||
// (inefficient because getFile iter on the list again)
|
// (inefficient because getFile iter on the list again)
|
||||||
Files::IStreamPtr data = bsa.getFile(archivePath);
|
Files::IStreamPtr data = bsa.getFile(file.name);
|
||||||
bfs::ofstream out(target, std::ios::binary);
|
bfs::ofstream out(target, std::ios::binary);
|
||||||
|
|
||||||
// Write the file to disk
|
// Write the file to disk
|
||||||
|
|
|
@ -352,12 +352,12 @@ int load(Arguments& info)
|
||||||
std::cout << "Author: " << esm.getAuthor() << std::endl
|
std::cout << "Author: " << esm.getAuthor() << std::endl
|
||||||
<< "Description: " << esm.getDesc() << std::endl
|
<< "Description: " << esm.getDesc() << std::endl
|
||||||
<< "File format version: " << esm.getFVer() << std::endl;
|
<< "File format version: " << esm.getFVer() << std::endl;
|
||||||
std::vector<ESM::Header::MasterData> m = esm.getGameFiles();
|
std::vector<ESM::Header::MasterData> masterData = esm.getGameFiles();
|
||||||
if (!m.empty())
|
if (!masterData.empty())
|
||||||
{
|
{
|
||||||
std::cout << "Masters:" << std::endl;
|
std::cout << "Masters:" << std::endl;
|
||||||
for(unsigned int i=0;i<m.size();i++)
|
for(const auto& master : masterData)
|
||||||
std::cout << " " << m[i].name << ", " << m[i].size << " bytes" << std::endl;
|
std::cout << " " << master.name << ", " << master.size << " bytes" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ int load(Arguments& info)
|
||||||
esm.getRecHeader(flags);
|
esm.getRecHeader(flags);
|
||||||
|
|
||||||
EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
|
EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
|
||||||
if (record == 0)
|
if (record == nullptr)
|
||||||
{
|
{
|
||||||
if (std::find(skipped.begin(), skipped.end(), n.intval) == skipped.end())
|
if (std::find(skipped.begin(), skipped.end(), n.intval) == skipped.end())
|
||||||
{
|
{
|
||||||
|
@ -538,8 +538,8 @@ int comp(Arguments& info)
|
||||||
Arguments fileOne;
|
Arguments fileOne;
|
||||||
Arguments fileTwo;
|
Arguments fileTwo;
|
||||||
|
|
||||||
fileOne.raw_given = 0;
|
fileOne.raw_given = false;
|
||||||
fileTwo.raw_given = 0;
|
fileTwo.raw_given = false;
|
||||||
|
|
||||||
fileOne.mode = "clone";
|
fileOne.mode = "clone";
|
||||||
fileTwo.mode = "clone";
|
fileTwo.mode = "clone";
|
||||||
|
|
|
@ -779,7 +779,7 @@ std::string creatureListFlags(int flags)
|
||||||
|
|
||||||
std::string lightFlags(int flags)
|
std::string lightFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties = "";
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0) properties += "[None] ";
|
||||||
if (flags & ESM::Light::Dynamic) properties += "Dynamic ";
|
if (flags & ESM::Light::Dynamic) properties += "Dynamic ";
|
||||||
if (flags & ESM::Light::Fire) properties += "Fire ";
|
if (flags & ESM::Light::Fire) properties += "Fire ";
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
void printAIPackage(ESM::AIPackage p)
|
void printAIPackage(const ESM::AIPackage& p)
|
||||||
{
|
{
|
||||||
std::cout << " AI Type: " << aiTypeLabel(p.mType)
|
std::cout << " AI Type: " << aiTypeLabel(p.mType)
|
||||||
<< " (" << Misc::StringUtils::format("0x%08X", p.mType) << ")" << std::endl;
|
<< " (" << Misc::StringUtils::format("0x%08X", p.mType) << ")" << std::endl;
|
||||||
|
@ -53,7 +53,7 @@ void printAIPackage(ESM::AIPackage p)
|
||||||
std::cout << " Cell Name: " << p.mCellName << std::endl;
|
std::cout << " Cell Name: " << p.mCellName << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ruleString(ESM::DialInfo::SelectStruct ss)
|
std::string ruleString(const ESM::DialInfo::SelectStruct& ss)
|
||||||
{
|
{
|
||||||
std::string rule = ss.mSelectRule;
|
std::string rule = ss.mSelectRule;
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printEffectList(ESM::EffectList effects)
|
void printEffectList(const ESM::EffectList& effects)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const ESM::ENAMstruct& effect : effects.mList)
|
for (const ESM::ENAMstruct& effect : effects.mList)
|
||||||
|
@ -174,7 +174,7 @@ namespace EsmTool {
|
||||||
RecordBase *
|
RecordBase *
|
||||||
RecordBase::create(ESM::NAME type)
|
RecordBase::create(ESM::NAME type)
|
||||||
{
|
{
|
||||||
RecordBase *record = 0;
|
RecordBase *record = nullptr;
|
||||||
|
|
||||||
switch (type.intval) {
|
switch (type.intval) {
|
||||||
case ESM::REC_ACTI:
|
case ESM::REC_ACTI:
|
||||||
|
@ -388,7 +388,7 @@ RecordBase::create(ESM::NAME type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
record = 0;
|
record = nullptr;
|
||||||
}
|
}
|
||||||
if (record) {
|
if (record) {
|
||||||
record->mType = type;
|
record->mType = type;
|
||||||
|
@ -728,10 +728,9 @@ void Record<ESM::Faction>::print()
|
||||||
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
||||||
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
||||||
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
||||||
for (int i = 0; i < 7; i++)
|
for (int skill : mData.mData.mSkills)
|
||||||
if (mData.mData.mSkills[i] != -1)
|
if (skill != -1)
|
||||||
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
|
std::cout << " Skill: " << skillLabel(skill) << " (" << skill << ")" << std::endl;
|
||||||
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
|
|
||||||
for (int i = 0; i != 10; i++)
|
for (int i = 0; i != 10; i++)
|
||||||
if (!mData.mRanks[i].empty())
|
if (!mData.mRanks[i].empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace EsmTool
|
||||||
: mIsDeleted(false)
|
: mIsDeleted(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string getId() const {
|
std::string getId() const override {
|
||||||
return mData.mId;
|
return mData.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,15 +82,15 @@ namespace EsmTool
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(ESM::ESMWriter &esm) {
|
void save(ESM::ESMWriter &esm) override {
|
||||||
mData.save(esm, mIsDeleted);
|
mData.save(esm, mIsDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(ESM::ESMReader &esm) {
|
void load(ESM::ESMReader &esm) override {
|
||||||
mData.load(esm, mIsDeleted);
|
mData.load(esm, mIsDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print();
|
void print() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> std::string Record<ESM::Cell>::getId() const;
|
template<> std::string Record<ESM::Cell>::getId() const;
|
||||||
|
|
|
@ -52,9 +52,7 @@ namespace
|
||||||
// a dynamically created record e.g. player-enchanted weapon
|
// a dynamically created record e.g. player-enchanted weapon
|
||||||
|
|
||||||
std::string index = indexedRefId.substr(indexedRefId.size()-8);
|
std::string index = indexedRefId.substr(indexedRefId.size()-8);
|
||||||
if(index.find_first_not_of("0123456789ABCDEF") == std::string::npos )
|
return index.find_first_not_of("0123456789ABCDEF") == std::string::npos;
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void splitIndexedRefId(const std::string& indexedRefId, int& refIndex, std::string& refId)
|
void splitIndexedRefId(const std::string& indexedRefId, int& refIndex, std::string& refId)
|
||||||
|
@ -139,12 +137,12 @@ namespace ESSImport
|
||||||
image2->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
|
image2->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||||
memcpy(image2->data(), &data[0], data.size());
|
memcpy(image2->data(), &data[0], data.size());
|
||||||
|
|
||||||
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
|
for (const auto & exploredCell : mContext->mExploredCells)
|
||||||
{
|
{
|
||||||
if (it->first > mContext->mGlobalMapState.mBounds.mMaxX
|
if (exploredCell.first > mContext->mGlobalMapState.mBounds.mMaxX
|
||||||
|| it->first < mContext->mGlobalMapState.mBounds.mMinX
|
|| exploredCell.first < mContext->mGlobalMapState.mBounds.mMinX
|
||||||
|| it->second > mContext->mGlobalMapState.mBounds.mMaxY
|
|| exploredCell.second > mContext->mGlobalMapState.mBounds.mMaxY
|
||||||
|| it->second < mContext->mGlobalMapState.mBounds.mMinY)
|
|| exploredCell.second < mContext->mGlobalMapState.mBounds.mMinY)
|
||||||
{
|
{
|
||||||
// out of bounds, I think this could happen, since the original engine had a fixed-size map
|
// out of bounds, I think this could happen, since the original engine had a fixed-size map
|
||||||
continue;
|
continue;
|
||||||
|
@ -152,12 +150,12 @@ namespace ESSImport
|
||||||
|
|
||||||
int imageLeftSrc = mGlobalMapImage->s()/2;
|
int imageLeftSrc = mGlobalMapImage->s()/2;
|
||||||
int imageTopSrc = mGlobalMapImage->t()/2;
|
int imageTopSrc = mGlobalMapImage->t()/2;
|
||||||
imageLeftSrc += it->first * cellSize;
|
imageLeftSrc += exploredCell.first * cellSize;
|
||||||
imageTopSrc -= it->second * cellSize;
|
imageTopSrc -= exploredCell.second * cellSize;
|
||||||
int imageLeftDst = width/2;
|
int imageLeftDst = width/2;
|
||||||
int imageTopDst = height/2;
|
int imageTopDst = height/2;
|
||||||
imageLeftDst += it->first * cellSize;
|
imageLeftDst += exploredCell.first * cellSize;
|
||||||
imageTopDst -= it->second * cellSize;
|
imageTopDst -= exploredCell.second * cellSize;
|
||||||
for (int x=0; x<cellSize; ++x)
|
for (int x=0; x<cellSize; ++x)
|
||||||
for (int y=0; y<cellSize; ++y)
|
for (int y=0; y<cellSize; ++y)
|
||||||
{
|
{
|
||||||
|
@ -329,9 +327,8 @@ namespace ESSImport
|
||||||
csta.mWaterLevel = esmcell.mWater;
|
csta.mWaterLevel = esmcell.mWater;
|
||||||
csta.save(esm);
|
csta.save(esm);
|
||||||
|
|
||||||
for (std::vector<CellRef>::const_iterator refIt = cell.mRefs.begin(); refIt != cell.mRefs.end(); ++refIt)
|
for (const auto & cellref : cell.mRefs)
|
||||||
{
|
{
|
||||||
const CellRef& cellref = *refIt;
|
|
||||||
ESM::CellRef out (cellref);
|
ESM::CellRef out (cellref);
|
||||||
|
|
||||||
// TODO: use mContext->mCreatures/mNpcs
|
// TODO: use mContext->mCreatures/mNpcs
|
||||||
|
@ -437,16 +434,16 @@ namespace ESSImport
|
||||||
|
|
||||||
void ConvertCell::write(ESM::ESMWriter &esm)
|
void ConvertCell::write(ESM::ESMWriter &esm)
|
||||||
{
|
{
|
||||||
for (std::map<std::string, Cell>::const_iterator it = mIntCells.begin(); it != mIntCells.end(); ++it)
|
for (const auto & cell : mIntCells)
|
||||||
writeCell(it->second, esm);
|
writeCell(cell.second, esm);
|
||||||
|
|
||||||
for (std::map<std::pair<int, int>, Cell>::const_iterator it = mExtCells.begin(); it != mExtCells.end(); ++it)
|
for (const auto & cell : mExtCells)
|
||||||
writeCell(it->second, esm);
|
writeCell(cell.second, esm);
|
||||||
|
|
||||||
for (std::vector<ESM::CustomMarker>::const_iterator it = mMarkers.begin(); it != mMarkers.end(); ++it)
|
for (const auto & marker : mMarkers)
|
||||||
{
|
{
|
||||||
esm.startRecord(ESM::REC_MARK);
|
esm.startRecord(ESM::REC_MARK);
|
||||||
it->save(esm);
|
marker.save(esm);
|
||||||
esm.endRecord(ESM::REC_MARK);
|
esm.endRecord(ESM::REC_MARK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,9 +79,9 @@ template <typename T>
|
||||||
class DefaultConverter : public Converter
|
class DefaultConverter : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int getStage() { return 0; }
|
int getStage() override { return 0; }
|
||||||
|
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
T record;
|
T record;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -90,7 +90,7 @@ public:
|
||||||
mRecords[record.mId] = record;
|
mRecords[record.mId] = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write(ESM::ESMWriter& esm)
|
void write(ESM::ESMWriter& esm) override
|
||||||
{
|
{
|
||||||
for (typename std::map<std::string, T>::const_iterator it = mRecords.begin(); it != mRecords.end(); ++it)
|
for (typename std::map<std::string, T>::const_iterator it = mRecords.begin(); it != mRecords.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +107,7 @@ protected:
|
||||||
class ConvertNPC : public Converter
|
class ConvertNPC : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
ESM::NPC npc;
|
ESM::NPC npc;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -127,8 +127,8 @@ public:
|
||||||
ESM::SpellState::SpellParams empty;
|
ESM::SpellState::SpellParams empty;
|
||||||
// FIXME: player start spells and birthsign spells aren't listed here,
|
// FIXME: player start spells and birthsign spells aren't listed here,
|
||||||
// need to fix openmw to account for this
|
// need to fix openmw to account for this
|
||||||
for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it)
|
for (const auto & spell : npc.mSpells.mList)
|
||||||
mContext->mPlayer.mObject.mCreatureStats.mSpells.mSpells[*it] = empty;
|
mContext->mPlayer.mObject.mCreatureStats.mSpells.mSpells[spell] = empty;
|
||||||
|
|
||||||
// Clear the list now that we've written it, this prevents issues cropping up with
|
// Clear the list now that we've written it, this prevents issues cropping up with
|
||||||
// ensureCustomData() in OpenMW tripping over no longer existing spells, where an error would be fatal.
|
// ensureCustomData() in OpenMW tripping over no longer existing spells, where an error would be fatal.
|
||||||
|
@ -144,7 +144,7 @@ public:
|
||||||
class ConvertCREA : public Converter
|
class ConvertCREA : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
// See comment in ConvertNPC
|
// See comment in ConvertNPC
|
||||||
ESM::Creature creature;
|
ESM::Creature creature;
|
||||||
|
@ -162,7 +162,7 @@ public:
|
||||||
class ConvertGlobal : public DefaultConverter<ESM::Global>
|
class ConvertGlobal : public DefaultConverter<ESM::Global>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
ESM::Global global;
|
ESM::Global global;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -183,7 +183,7 @@ public:
|
||||||
class ConvertClass : public DefaultConverter<ESM::Class>
|
class ConvertClass : public DefaultConverter<ESM::Class>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
ESM::Class class_;
|
ESM::Class class_;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -199,7 +199,7 @@ public:
|
||||||
class ConvertBook : public DefaultConverter<ESM::Book>
|
class ConvertBook : public DefaultConverter<ESM::Book>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
ESM::Book book;
|
ESM::Book book;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -215,7 +215,7 @@ public:
|
||||||
class ConvertNPCC : public Converter
|
class ConvertNPCC : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
NPCC npcc;
|
NPCC npcc;
|
||||||
|
@ -235,7 +235,7 @@ public:
|
||||||
class ConvertREFR : public Converter
|
class ConvertREFR : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
REFR refr;
|
REFR refr;
|
||||||
refr.load(esm);
|
refr.load(esm);
|
||||||
|
@ -261,7 +261,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void write(ESM::ESMWriter& esm)
|
void write(ESM::ESMWriter& esm) override
|
||||||
{
|
{
|
||||||
esm.startRecord(ESM::REC_ASPL);
|
esm.startRecord(ESM::REC_ASPL);
|
||||||
esm.writeHNString("ID__", mSelectedSpell);
|
esm.writeHNString("ID__", mSelectedSpell);
|
||||||
|
@ -280,14 +280,14 @@ public:
|
||||||
mLevitationEnabled(true)
|
mLevitationEnabled(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
PCDT pcdt;
|
PCDT pcdt;
|
||||||
pcdt.load(esm);
|
pcdt.load(esm);
|
||||||
|
|
||||||
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam, mTeleportingEnabled, mLevitationEnabled, mContext->mControlsState);
|
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam, mTeleportingEnabled, mLevitationEnabled, mContext->mControlsState);
|
||||||
}
|
}
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
esm.startRecord(ESM::REC_ENAB);
|
esm.startRecord(ESM::REC_ENAB);
|
||||||
esm.writeHNT("TELE", mTeleportingEnabled);
|
esm.writeHNT("TELE", mTeleportingEnabled);
|
||||||
|
@ -306,7 +306,7 @@ private:
|
||||||
|
|
||||||
class ConvertCNTC : public Converter
|
class ConvertCNTC : public Converter
|
||||||
{
|
{
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
CNTC cntc;
|
CNTC cntc;
|
||||||
|
@ -318,7 +318,7 @@ class ConvertCNTC : public Converter
|
||||||
class ConvertCREC : public Converter
|
class ConvertCREC : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
CREC crec;
|
CREC crec;
|
||||||
|
@ -330,8 +330,8 @@ public:
|
||||||
class ConvertFMAP : public Converter
|
class ConvertFMAP : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm);
|
void read(ESM::ESMReader &esm) override;
|
||||||
virtual void write(ESM::ESMWriter &esm);
|
void write(ESM::ESMWriter &esm) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Image> mGlobalMapImage;
|
osg::ref_ptr<osg::Image> mGlobalMapImage;
|
||||||
|
@ -340,8 +340,8 @@ private:
|
||||||
class ConvertCell : public Converter
|
class ConvertCell : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm);
|
void read(ESM::ESMReader& esm) override;
|
||||||
virtual void write(ESM::ESMWriter& esm);
|
void write(ESM::ESMWriter& esm) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Cell
|
struct Cell
|
||||||
|
@ -362,7 +362,7 @@ private:
|
||||||
class ConvertKLST : public Converter
|
class ConvertKLST : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
KLST klst;
|
KLST klst;
|
||||||
klst.load(esm);
|
klst.load(esm);
|
||||||
|
@ -371,7 +371,7 @@ public:
|
||||||
mContext->mPlayer.mObject.mNpcStats.mWerewolfKills = klst.mWerewolfKills;
|
mContext->mPlayer.mObject.mNpcStats.mWerewolfKills = klst.mWerewolfKills;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
esm.startRecord(ESM::REC_DCOU);
|
esm.startRecord(ESM::REC_DCOU);
|
||||||
for (std::map<std::string, int>::const_iterator it = mKillCounter.begin(); it != mKillCounter.end(); ++it)
|
for (std::map<std::string, int>::const_iterator it = mKillCounter.begin(); it != mKillCounter.end(); ++it)
|
||||||
|
@ -389,7 +389,7 @@ private:
|
||||||
class ConvertFACT : public Converter
|
class ConvertFACT : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
ESM::Faction faction;
|
ESM::Faction faction;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
@ -409,7 +409,7 @@ public:
|
||||||
class ConvertSTLN : public Converter
|
class ConvertSTLN : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
std::string itemid = esm.getHNString("NAME");
|
std::string itemid = esm.getHNString("NAME");
|
||||||
Misc::StringUtils::lowerCaseInPlace(itemid);
|
Misc::StringUtils::lowerCaseInPlace(itemid);
|
||||||
|
@ -428,15 +428,15 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
ESM::StolenItems items;
|
ESM::StolenItems items;
|
||||||
for (std::map<std::string, std::set<Owner> >::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
|
for (std::map<std::string, std::set<Owner> >::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
|
||||||
{
|
{
|
||||||
std::map<std::pair<std::string, bool>, int> owners;
|
std::map<std::pair<std::string, bool>, int> owners;
|
||||||
for (std::set<Owner>::const_iterator ownerIt = it->second.begin(); ownerIt != it->second.end(); ++ownerIt)
|
for (const auto & ownerIt : it->second)
|
||||||
{
|
{
|
||||||
owners.insert(std::make_pair(std::make_pair(ownerIt->first, ownerIt->second)
|
owners.insert(std::make_pair(std::make_pair(ownerIt.first, ownerIt.second)
|
||||||
// Since OpenMW doesn't suffer from the owner contamination bug,
|
// Since OpenMW doesn't suffer from the owner contamination bug,
|
||||||
// it needs a count argument. But for legacy savegames, we don't know
|
// it needs a count argument. But for legacy savegames, we don't know
|
||||||
// this count, so must assume all items of that ID are stolen,
|
// this count, so must assume all items of that ID are stolen,
|
||||||
|
@ -467,7 +467,7 @@ private:
|
||||||
class ConvertINFO : public Converter
|
class ConvertINFO : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
INFO info;
|
INFO info;
|
||||||
info.load(esm);
|
info.load(esm);
|
||||||
|
@ -477,7 +477,7 @@ public:
|
||||||
class ConvertDIAL : public Converter
|
class ConvertDIAL : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
DIAL dial;
|
DIAL dial;
|
||||||
|
@ -485,7 +485,7 @@ public:
|
||||||
if (dial.mIndex > 0)
|
if (dial.mIndex > 0)
|
||||||
mDials[id] = dial;
|
mDials[id] = dial;
|
||||||
}
|
}
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
for (std::map<std::string, DIAL>::const_iterator it = mDials.begin(); it != mDials.end(); ++it)
|
for (std::map<std::string, DIAL>::const_iterator it = mDials.begin(); it != mDials.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -505,7 +505,7 @@ private:
|
||||||
class ConvertQUES : public Converter
|
class ConvertQUES : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
QUES quest;
|
QUES quest;
|
||||||
|
@ -516,7 +516,7 @@ public:
|
||||||
class ConvertJOUR : public Converter
|
class ConvertJOUR : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm)
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
JOUR journal;
|
JOUR journal;
|
||||||
journal.load(esm);
|
journal.load(esm);
|
||||||
|
@ -531,7 +531,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
mGame.load(esm);
|
mGame.load(esm);
|
||||||
mHasGame = true;
|
mHasGame = true;
|
||||||
|
@ -551,7 +551,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
if (!mHasGame)
|
if (!mHasGame)
|
||||||
return;
|
return;
|
||||||
|
@ -578,7 +578,7 @@ private:
|
||||||
class ConvertSCPT : public Converter
|
class ConvertSCPT : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader &esm)
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
SCPT script;
|
SCPT script;
|
||||||
script.load(esm);
|
script.load(esm);
|
||||||
|
@ -586,12 +586,12 @@ public:
|
||||||
convertSCPT(script, out);
|
convertSCPT(script, out);
|
||||||
mScripts.push_back(out);
|
mScripts.push_back(out);
|
||||||
}
|
}
|
||||||
virtual void write(ESM::ESMWriter &esm)
|
void write(ESM::ESMWriter &esm) override
|
||||||
{
|
{
|
||||||
for (std::vector<ESM::GlobalScript>::const_iterator it = mScripts.begin(); it != mScripts.end(); ++it)
|
for (const auto & script : mScripts)
|
||||||
{
|
{
|
||||||
esm.startRecord(ESM::REC_GSCR);
|
esm.startRecord(ESM::REC_GSCR);
|
||||||
it->save(esm);
|
script.save(esm);
|
||||||
esm.endRecord(ESM::REC_GSCR);
|
esm.endRecord(ESM::REC_GSCR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,9 +603,9 @@ private:
|
||||||
class ConvertPROJ : public Converter
|
class ConvertPROJ : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int getStage() override { return 2; }
|
int getStage() override { return 2; }
|
||||||
virtual void read(ESM::ESMReader& esm) override;
|
void read(ESM::ESMReader& esm) override;
|
||||||
virtual void write(ESM::ESMWriter& esm) override;
|
void write(ESM::ESMWriter& esm) override;
|
||||||
private:
|
private:
|
||||||
void convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam);
|
void convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam);
|
||||||
PROJ mProj;
|
PROJ mProj;
|
||||||
|
@ -614,8 +614,8 @@ private:
|
||||||
class ConvertSPLM : public Converter
|
class ConvertSPLM : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void read(ESM::ESMReader& esm) override;
|
void read(ESM::ESMReader& esm) override;
|
||||||
virtual void write(ESM::ESMWriter& esm) override;
|
void write(ESM::ESMWriter& esm) override;
|
||||||
private:
|
private:
|
||||||
SPLM mSPLM;
|
SPLM mSPLM;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,21 +9,20 @@ namespace ESSImport
|
||||||
void convertInventory(const Inventory &inventory, ESM::InventoryState &state)
|
void convertInventory(const Inventory &inventory, ESM::InventoryState &state)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (std::vector<Inventory::InventoryItem>::const_iterator it = inventory.mItems.begin();
|
for (const auto & item : inventory.mItems)
|
||||||
it != inventory.mItems.end(); ++it)
|
|
||||||
{
|
{
|
||||||
ESM::ObjectState objstate;
|
ESM::ObjectState objstate;
|
||||||
objstate.blank();
|
objstate.blank();
|
||||||
objstate.mRef = *it;
|
objstate.mRef = item;
|
||||||
objstate.mRef.mRefID = Misc::StringUtils::lowerCase(it->mId);
|
objstate.mRef.mRefID = Misc::StringUtils::lowerCase(item.mId);
|
||||||
objstate.mCount = std::abs(it->mCount); // restocking items have negative count in the savefile
|
objstate.mCount = std::abs(item.mCount); // restocking items have negative count in the savefile
|
||||||
// openmw handles them differently, so no need to set any flags
|
// openmw handles them differently, so no need to set any flags
|
||||||
state.mItems.push_back(objstate);
|
state.mItems.push_back(objstate);
|
||||||
if (it->mRelativeEquipmentSlot != -1)
|
if (item.mRelativeEquipmentSlot != -1)
|
||||||
// Note we should really write the absolute slot here, which we do not know about
|
// Note we should really write the absolute slot here, which we do not know about
|
||||||
// Not a big deal, OpenMW will auto-correct to a valid slot, the only problem is when
|
// Not a big deal, OpenMW will auto-correct to a valid slot, the only problem is when
|
||||||
// an item could be equipped in two different slots (e.g. equipped two rings)
|
// an item could be equipped in two different slots (e.g. equipped two rings)
|
||||||
state.mEquipmentSlots[index] = it->mRelativeEquipmentSlot;
|
state.mEquipmentSlots[index] = item.mRelativeEquipmentSlot;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,13 @@ namespace ESSImport
|
||||||
{
|
{
|
||||||
out.mBirthsign = pcdt.mBirthsign;
|
out.mBirthsign = pcdt.mBirthsign;
|
||||||
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||||
for (std::vector<PCDT::FNAM>::const_iterator it = pcdt.mFactions.begin(); it != pcdt.mFactions.end(); ++it)
|
for (const auto & essFaction : pcdt.mFactions)
|
||||||
{
|
{
|
||||||
ESM::NpcStats::Faction faction;
|
ESM::NpcStats::Faction faction;
|
||||||
faction.mExpelled = (it->mFlags & 0x2) != 0;
|
faction.mExpelled = (essFaction.mFlags & 0x2) != 0;
|
||||||
faction.mRank = it->mRank;
|
faction.mRank = essFaction.mRank;
|
||||||
faction.mReputation = it->mReputation;
|
faction.mReputation = essFaction.mReputation;
|
||||||
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(it->mFactionName.toString())] = faction;
|
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(essFaction.mFactionName.toString())] = faction;
|
||||||
}
|
}
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
|
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
|
||||||
|
@ -35,10 +35,9 @@ namespace ESSImport
|
||||||
teleportingEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_TeleportingDisabled);
|
teleportingEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_TeleportingDisabled);
|
||||||
levitationEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_LevitationDisabled);
|
levitationEnabled = !(pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_LevitationDisabled);
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
|
for (const auto & knownDialogueTopic : pcdt.mKnownDialogueTopics)
|
||||||
it != pcdt.mKnownDialogueTopics.end(); ++it)
|
|
||||||
{
|
{
|
||||||
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(*it));
|
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(knownDialogueTopic));
|
||||||
}
|
}
|
||||||
|
|
||||||
controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;
|
controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
#include "convertscri.hpp"
|
#include "convertscri.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename T, ESM::VarType VariantType>
|
template <typename T, ESM::VarType VariantType>
|
||||||
void storeVariables(const std::vector<T>& variables, ESM::Locals& locals, const std::string& scriptname)
|
void storeVariables(const std::vector<T>& variables, ESM::Locals& locals, const std::string& scriptname)
|
||||||
{
|
{
|
||||||
for (typename std::vector<T>::const_iterator it = variables.begin(); it != variables.end(); ++it)
|
for (const auto& variable : variables)
|
||||||
{
|
{
|
||||||
ESM::Variant val(*it);
|
ESM::Variant val(variable);
|
||||||
val.setType(VariantType);
|
val.setType(VariantType);
|
||||||
locals.mVariables.push_back(std::make_pair(std::string(), val));
|
locals.mVariables.emplace_back(std::string(), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,9 @@ namespace ESSImport
|
||||||
bool mHasANIS;
|
bool mHasANIS;
|
||||||
ANIS mANIS; // scripted animation state
|
ANIS mANIS; // scripted animation state
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm);
|
virtual void load(ESM::ESMReader& esm);
|
||||||
|
|
||||||
|
virtual ~ActorData() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,9 @@ namespace ESSImport
|
||||||
|
|
||||||
bool mDeleted;
|
bool mDeleted;
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm);
|
void load(ESM::ESMReader& esm) override;
|
||||||
|
|
||||||
|
virtual ~CellRef() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,12 @@
|
||||||
#include <components/esm/player.hpp>
|
#include <components/esm/player.hpp>
|
||||||
|
|
||||||
#include <components/esm/loadalch.hpp>
|
#include <components/esm/loadalch.hpp>
|
||||||
#include <components/esm/loadclas.hpp>
|
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
#include <components/esm/loadarmo.hpp>
|
#include <components/esm/loadarmo.hpp>
|
||||||
#include <components/esm/loadweap.hpp>
|
#include <components/esm/loadweap.hpp>
|
||||||
#include <components/esm/loadclot.hpp>
|
#include <components/esm/loadclot.hpp>
|
||||||
#include <components/esm/loadench.hpp>
|
#include <components/esm/loadench.hpp>
|
||||||
#include <components/esm/loadweap.hpp>
|
|
||||||
#include <components/esm/loadlevlist.hpp>
|
#include <components/esm/loadlevlist.hpp>
|
||||||
#include <components/esm/loadglob.hpp>
|
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
|
@ -49,7 +46,7 @@ namespace
|
||||||
image->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
image->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
||||||
|
|
||||||
// need to convert pixel format from BGRA to RGB as the jpg readerwriter doesn't support it otherwise
|
// need to convert pixel format from BGRA to RGB as the jpg readerwriter doesn't support it otherwise
|
||||||
std::vector<unsigned char>::const_iterator it = fileHeader.mSCRS.begin();
|
auto it = fileHeader.mSCRS.begin();
|
||||||
for (int y=0; y<128; ++y)
|
for (int y=0; y<128; ++y)
|
||||||
{
|
{
|
||||||
for (int x=0; x<128; ++x)
|
for (int x=0; x<128; ++x)
|
||||||
|
@ -317,10 +314,9 @@ namespace ESSImport
|
||||||
|
|
||||||
std::set<unsigned int> unknownRecords;
|
std::set<unsigned int> unknownRecords;
|
||||||
|
|
||||||
for (std::map<unsigned int, std::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
for (const auto & converter : converters)
|
||||||
it != converters.end(); ++it)
|
|
||||||
{
|
{
|
||||||
it->second->setContext(context);
|
converter.second->setContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (esm.hasMoreRecs())
|
while (esm.hasMoreRecs())
|
||||||
|
@ -328,7 +324,7 @@ namespace ESSImport
|
||||||
ESM::NAME n = esm.getRecName();
|
ESM::NAME n = esm.getRecName();
|
||||||
esm.getRecHeader();
|
esm.getRecHeader();
|
||||||
|
|
||||||
std::map<unsigned int, std::shared_ptr<Converter> >::iterator it = converters.find(n.intval);
|
auto it = converters.find(n.intval);
|
||||||
if (it != converters.end())
|
if (it != converters.end())
|
||||||
{
|
{
|
||||||
it->second->read(esm);
|
it->second->read(esm);
|
||||||
|
@ -358,17 +354,15 @@ namespace ESSImport
|
||||||
writer.setDescription("");
|
writer.setDescription("");
|
||||||
writer.setRecordCount (0);
|
writer.setRecordCount (0);
|
||||||
|
|
||||||
for (std::vector<ESM::Header::MasterData>::const_iterator it = header.mMaster.begin();
|
for (const auto & master : header.mMaster)
|
||||||
it != header.mMaster.end(); ++it)
|
writer.addMaster(master.name, 0); // not using the size information anyway -> use value of 0
|
||||||
writer.addMaster (it->name, 0); // not using the size information anyway -> use value of 0
|
|
||||||
|
|
||||||
writer.save (stream);
|
writer.save (stream);
|
||||||
|
|
||||||
ESM::SavedGame profile;
|
ESM::SavedGame profile;
|
||||||
for (std::vector<ESM::Header::MasterData>::const_iterator it = header.mMaster.begin();
|
for (const auto & master : header.mMaster)
|
||||||
it != header.mMaster.end(); ++it)
|
|
||||||
{
|
{
|
||||||
profile.mContentFiles.push_back(it->name);
|
profile.mContentFiles.push_back(master.name);
|
||||||
}
|
}
|
||||||
profile.mDescription = esm.getDesc();
|
profile.mDescription = esm.getDesc();
|
||||||
profile.mInGameTime.mDay = context.mDay;
|
profile.mInGameTime.mDay = context.mDay;
|
||||||
|
|
|
@ -63,7 +63,6 @@ namespace ESSImport
|
||||||
, mHour(0.f)
|
, mHour(0.f)
|
||||||
, mNextActorId(0)
|
, mNextActorId(0)
|
||||||
{
|
{
|
||||||
mPlayer.mAutoMove = 0;
|
|
||||||
ESM::CellId playerCellId;
|
ESM::CellId playerCellId;
|
||||||
playerCellId.mPaged = true;
|
playerCellId.mPaged = true;
|
||||||
playerCellId.mIndex.mX = playerCellId.mIndex.mY = 0;
|
playerCellId.mIndex.mX = playerCellId.mIndex.mY = 0;
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
#include <components/esm/loadcont.hpp>
|
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,10 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
|
||||||
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
|
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
|
||||||
|
|
||||||
// Check BYDT
|
// Check BYDT
|
||||||
if (bodyPart.mData.mPart > 14 )
|
if (bodyPart.mData.mPart >= ESM::BodyPart::MP_Count )
|
||||||
messages.add(id, "Invalid part", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Invalid part", "", CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
if (bodyPart.mData.mFlags > 3 )
|
if (bodyPart.mData.mType > ESM::BodyPart::MT_Armor )
|
||||||
messages.add(id, "Invalid flags", "", CSMDoc::Message::Severity_Error);
|
|
||||||
|
|
||||||
if (bodyPart.mData.mType > 2 )
|
|
||||||
messages.add(id, "Invalid type", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Invalid type", "", CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
// Check MODL
|
// Check MODL
|
||||||
|
@ -48,9 +45,12 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
|
||||||
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
|
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
|
||||||
messages.add(id, "Model '" + bodyPart.mModel + "' does not exist", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Model '" + bodyPart.mModel + "' does not exist", "", CSMDoc::Message::Severity_Error);
|
||||||
|
|
||||||
// Check FNAM
|
// Check FNAM for skin body parts (for non-skin body parts it's meaningless)
|
||||||
if ( bodyPart.mRace.empty() )
|
if ( bodyPart.mData.mType == ESM::BodyPart::MT_Skin )
|
||||||
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
|
{
|
||||||
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
|
if ( bodyPart.mRace.empty() )
|
||||||
messages.add(id, "Race '" + bodyPart.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
|
||||||
|
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
|
||||||
|
messages.add(id, "Race '" + bodyPart.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,12 @@ add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh
|
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
inputmanagerimp
|
actions actionmanager bindingsmanager controllermanager controlswitch
|
||||||
|
inputmanagerimp mousemanager keyboardmanager sdlmappings sensormanager
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwgui
|
add_openmw_dir (mwgui
|
||||||
|
@ -40,7 +41,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
|
||||||
|
@ -66,7 +67,7 @@ add_openmw_dir (mwworld
|
||||||
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
||||||
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
||||||
contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
|
contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
|
||||||
cellpreloader
|
cellpreloader datetimemanager
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwphysics
|
add_openmw_dir (mwphysics
|
||||||
|
@ -83,9 +84,10 @@ add_openmw_dir (mwclass
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat creaturestats magiceffects movement actorutil
|
mechanicsmanagerimp stat creaturestats magiceffects movement actorutil
|
||||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
||||||
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
|
||||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
||||||
character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype
|
character actors objects aistate trading weaponpriority spellpriority weapontype spellutil tickableeffects
|
||||||
|
spellabsorption linkedeffects
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwstate
|
add_openmw_dir (mwstate
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ bool OMW::Engine::frame(float frametime)
|
||||||
// When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
|
// When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
|
||||||
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
|
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
|
||||||
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
|
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
|
||||||
if (!mEnvironment.getInputManager()->isWindowVisible())
|
if (!mEnvironment.getWindowManager()->isWindowVisible())
|
||||||
{
|
{
|
||||||
mEnvironment.getSoundManager()->pausePlayback();
|
mEnvironment.getSoundManager()->pausePlayback();
|
||||||
return false;
|
return false;
|
||||||
|
@ -180,7 +181,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();
|
||||||
|
@ -202,12 +203,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -532,20 +535,20 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
else
|
else
|
||||||
gameControllerdb = ""; //if it doesn't exist, pass in an empty string
|
gameControllerdb = ""; //if it doesn't exist, pass in an empty string
|
||||||
|
|
||||||
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
|
||||||
mEnvironment.setInputManager (input);
|
|
||||||
|
|
||||||
std::string myguiResources = (mResDir / "mygui").string();
|
std::string myguiResources = (mResDir / "mygui").string();
|
||||||
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
|
osg::ref_ptr<osg::Group> guiRoot = new osg::Group;
|
||||||
guiRoot->setName("GUI Root");
|
guiRoot->setName("GUI Root");
|
||||||
guiRoot->setNodeMask(MWRender::Mask_GUI);
|
guiRoot->setNodeMask(MWRender::Mask_GUI);
|
||||||
rootNode->addChild(guiRoot);
|
rootNode->addChild(guiRoot);
|
||||||
MWGui::WindowManager* window = new MWGui::WindowManager(mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
MWGui::WindowManager* window = new MWGui::WindowManager(mWindow, mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
|
||||||
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
mCfgMgr.getLogPath().string() + std::string("/"), myguiResources,
|
||||||
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
|
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts,
|
||||||
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
Version::getOpenmwVersionDescription(mResDir.string()), mCfgMgr.getUserConfigPath().string());
|
||||||
mEnvironment.setWindowManager (window);
|
mEnvironment.setWindowManager (window);
|
||||||
|
|
||||||
|
MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, userGameControllerdb, gameControllerdb, mGrab);
|
||||||
|
mEnvironment.setInputManager (input);
|
||||||
|
|
||||||
// Create sound system
|
// Create sound system
|
||||||
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
|
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
|
||||||
|
|
||||||
|
@ -561,7 +564,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
mFileCollections, mContentFiles, mEncoder, mActivationDistanceOverride, mCellName,
|
mFileCollections, mContentFiles, mEncoder, mActivationDistanceOverride, mCellName,
|
||||||
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()));
|
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()));
|
||||||
mEnvironment.getWorld()->setupPlayer();
|
mEnvironment.getWorld()->setupPlayer();
|
||||||
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
|
|
||||||
|
|
||||||
window->setStore(mEnvironment.getWorld()->getStore());
|
window->setStore(mEnvironment.getWorld()->getStore());
|
||||||
window->initUI();
|
window->initUI();
|
||||||
|
@ -658,7 +660,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialise and enter main loop.
|
// Initialise and enter main loop.
|
||||||
|
|
||||||
void OMW::Engine::go()
|
void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
assert (!mContentFiles.empty());
|
assert (!mContentFiles.empty());
|
||||||
|
@ -687,7 +688,8 @@ void OMW::Engine::go()
|
||||||
mViewer->setUseConfigureAffinity(false);
|
mViewer->setUseConfigureAffinity(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(),
|
mScreenCaptureOperation = new WriteScreenshotToFileOperation(
|
||||||
|
mCfgMgr.getScreenshotPath().string(),
|
||||||
Settings::Manager::getString("screenshot format", "General"));
|
Settings::Manager::getString("screenshot format", "General"));
|
||||||
|
|
||||||
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation);
|
mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation);
|
||||||
|
@ -739,6 +741,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;
|
||||||
|
@ -769,6 +779,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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,6 @@ namespace MWBase
|
||||||
|
|
||||||
virtual ~InputManager() {}
|
virtual ~InputManager() {}
|
||||||
|
|
||||||
virtual bool isWindowVisible() = 0;
|
|
||||||
|
|
||||||
virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0;
|
virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0;
|
||||||
|
|
||||||
virtual void changeInputMode(bool guiMode) = 0;
|
virtual void changeInputMode(bool guiMode) = 0;
|
||||||
|
@ -47,6 +45,8 @@ namespace MWBase
|
||||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||||
|
|
||||||
virtual void setDragDrop(bool dragDrop) = 0;
|
virtual void setDragDrop(bool dragDrop) = 0;
|
||||||
|
virtual void setGamepadGuiCursorEnabled(bool enabled) = 0;
|
||||||
|
virtual void setAttemptJump(bool jumping) = 0;
|
||||||
|
|
||||||
virtual void toggleControlSwitch (const std::string& sw, bool value) = 0;
|
virtual void toggleControlSwitch (const std::string& sw, bool value) = 0;
|
||||||
virtual bool getControlSwitch (const std::string& sw) = 0;
|
virtual bool getControlSwitch (const std::string& sw) = 0;
|
||||||
|
@ -54,8 +54,6 @@ namespace MWBase
|
||||||
virtual std::string getActionDescription (int action) = 0;
|
virtual std::string getActionDescription (int action) = 0;
|
||||||
virtual std::string getActionKeyBindingName (int action) = 0;
|
virtual std::string getActionKeyBindingName (int action) = 0;
|
||||||
virtual std::string getActionControllerBindingName (int action) = 0;
|
virtual std::string getActionControllerBindingName (int action) = 0;
|
||||||
virtual std::string sdlControllerAxisToString(int axis) = 0;
|
|
||||||
virtual std::string sdlControllerButtonToString(int button) = 0;
|
|
||||||
///Actions available for binding to keyboard buttons
|
///Actions available for binding to keyboard buttons
|
||||||
virtual std::vector<int> getActionKeySorting() = 0;
|
virtual std::vector<int> getActionKeySorting() = 0;
|
||||||
///Actions available for binding to controller buttons
|
///Actions available for binding to controller buttons
|
||||||
|
@ -69,10 +67,17 @@ namespace MWBase
|
||||||
/// Returns if the last used input device was a joystick or a keyboard
|
/// Returns if the last used input device was a joystick or a keyboard
|
||||||
/// @return true if joystick, false otherwise
|
/// @return true if joystick, false otherwise
|
||||||
virtual bool joystickLastUsed() = 0;
|
virtual bool joystickLastUsed() = 0;
|
||||||
|
virtual void setJoystickLastUsed(bool enabled) = 0;
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const = 0;
|
virtual int countSavedGameRecords() const = 0;
|
||||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
|
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
|
||||||
|
|
||||||
|
virtual void resetIdleTime() = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +273,15 @@ 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;
|
||||||
|
|
||||||
|
virtual void restoreStatsAfterCorprus(const MWWorld::Ptr& actor, const std::string& sourceId) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual ~ScriptManager() {}
|
virtual ~ScriptManager() {}
|
||||||
|
|
||||||
virtual void run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0;
|
||||||
///< Run the script with the given name (compile first, if not compiled yet)
|
///< Run the script with the given name (compile first, if not compiled yet)
|
||||||
|
|
||||||
virtual bool compile (const std::string& name) = 0;
|
virtual bool compile (const std::string& name) = 0;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "../mwgui/mode.hpp"
|
#include "../mwgui/mode.hpp"
|
||||||
|
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
{
|
{
|
||||||
class Listener;
|
class Listener;
|
||||||
|
@ -86,7 +88,7 @@ namespace SFO
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
{
|
{
|
||||||
/// \brief Interface for widnow manager (implemented in MWGui)
|
/// \brief Interface for widnow manager (implemented in MWGui)
|
||||||
class WindowManager
|
class WindowManager : public SDLUtil::WindowListener
|
||||||
{
|
{
|
||||||
WindowManager (const WindowManager&);
|
WindowManager (const WindowManager&);
|
||||||
///< not implemented
|
///< not implemented
|
||||||
|
@ -249,13 +251,7 @@ namespace MWBase
|
||||||
/// returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
/// returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||||
virtual int readPressedButton() = 0;
|
virtual int readPressedButton() = 0;
|
||||||
|
|
||||||
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
|
||||||
|
@ -268,8 +264,6 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||||
|
|
||||||
virtual void windowResized(int x, int y) = 0;
|
|
||||||
|
|
||||||
virtual void executeInConsole (const std::string& path) = 0;
|
virtual void executeInConsole (const std::string& path) = 0;
|
||||||
|
|
||||||
virtual void enableRest() = 0;
|
virtual void enableRest() = 0;
|
||||||
|
@ -360,6 +354,11 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0;
|
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0;
|
||||||
virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0;
|
virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0;
|
||||||
|
|
||||||
|
virtual void windowVisibilityChange(bool visible) = 0;
|
||||||
|
virtual void windowResized(int x, int y) = 0;
|
||||||
|
virtual void windowClosed() = 0;
|
||||||
|
virtual bool isWindowVisible() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace osg
|
||||||
class Matrixf;
|
class Matrixf;
|
||||||
class Quat;
|
class Quat;
|
||||||
class Image;
|
class Image;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
|
@ -35,6 +36,7 @@ namespace ESM
|
||||||
struct Position;
|
struct Position;
|
||||||
struct Cell;
|
struct Cell;
|
||||||
struct Class;
|
struct Class;
|
||||||
|
struct Creature;
|
||||||
struct Potion;
|
struct Potion;
|
||||||
struct Spell;
|
struct Spell;
|
||||||
struct NPC;
|
struct NPC;
|
||||||
|
@ -46,6 +48,7 @@ namespace ESM
|
||||||
struct EffectList;
|
struct EffectList;
|
||||||
struct CreatureLevList;
|
struct CreatureLevList;
|
||||||
struct ItemLevList;
|
struct ItemLevList;
|
||||||
|
struct TimeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -189,6 +192,8 @@ namespace MWBase
|
||||||
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
||||||
///< Search is limited to the active cells.
|
///< Search is limited to the active cells.
|
||||||
|
|
||||||
|
virtual MWWorld::Ptr searchPtrViaRefNum (const std::string& id, const ESM::RefNum& refNum) = 0;
|
||||||
|
|
||||||
virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0;
|
virtual MWWorld::Ptr findContainer (const MWWorld::ConstPtr& ptr) = 0;
|
||||||
///< Return a pointer to a liveCellRef which contains \a ptr.
|
///< Return a pointer to a liveCellRef which contains \a ptr.
|
||||||
/// \note Search is limited to the active cells.
|
/// \note Search is limited to the active cells.
|
||||||
|
@ -200,24 +205,14 @@ namespace MWBase
|
||||||
virtual void advanceTime (double hours, bool incremental = false) = 0;
|
virtual void advanceTime (double hours, bool incremental = false) = 0;
|
||||||
///< Advance in-game time.
|
///< Advance in-game time.
|
||||||
|
|
||||||
virtual void setHour (double hour) = 0;
|
|
||||||
///< Set in-game time hour.
|
|
||||||
|
|
||||||
virtual void setMonth (int month) = 0;
|
|
||||||
///< Set in-game time month.
|
|
||||||
|
|
||||||
virtual void setDay (int day) = 0;
|
|
||||||
///< Set in-game time day.
|
|
||||||
|
|
||||||
virtual int getDay() const = 0;
|
|
||||||
virtual int getMonth() const = 0;
|
|
||||||
virtual int getYear() const = 0;
|
|
||||||
|
|
||||||
virtual std::string getMonthName (int month = -1) const = 0;
|
virtual std::string getMonthName (int month = -1) const = 0;
|
||||||
///< Return name of month (-1: current month)
|
///< Return name of month (-1: current month)
|
||||||
|
|
||||||
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
|
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
|
||||||
///< Return current in-game time stamp.
|
///< Return current in-game time and number of day since new game start.
|
||||||
|
|
||||||
|
virtual ESM::EpochTimeStamp getEpochTimeStamp() const = 0;
|
||||||
|
///< Return current in-game date and time.
|
||||||
|
|
||||||
virtual bool toggleSky() = 0;
|
virtual bool toggleSky() = 0;
|
||||||
///< \return Resulting mode
|
///< \return Resulting mode
|
||||||
|
@ -375,6 +370,14 @@ namespace MWBase
|
||||||
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||||
/// \return pointer to created record
|
/// \return pointer to created record
|
||||||
|
|
||||||
|
virtual const ESM::Creature *createOverrideRecord (const ESM::Creature& record) = 0;
|
||||||
|
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||||
|
/// \return pointer to created record
|
||||||
|
|
||||||
|
virtual const ESM::NPC *createOverrideRecord (const ESM::NPC& record) = 0;
|
||||||
|
///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID.
|
||||||
|
/// \return pointer to created record
|
||||||
|
|
||||||
virtual void update (float duration, bool paused) = 0;
|
virtual void update (float duration, bool paused) = 0;
|
||||||
virtual void updatePhysics (float duration, bool paused) = 0;
|
virtual void updatePhysics (float duration, bool paused) = 0;
|
||||||
|
|
||||||
|
@ -627,6 +630,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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ namespace MWClass
|
||||||
const MWWorld::LiveCellRef<ESM::Armor> *ref = ptr.get<ESM::Armor>();
|
const MWWorld::LiveCellRef<ESM::Armor> *ref = ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
int armorSkillType = getEquipmentSkill(ptr);
|
int armorSkillType = getEquipmentSkill(ptr);
|
||||||
int armorSkill = actor.getClass().getSkill(actor, armorSkillType);
|
float armorSkill = actor.getClass().getSkill(actor, armorSkillType);
|
||||||
|
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
int iBaseArmorSkill = world->getStore().get<ESM::GameSetting>().find("iBaseArmorSkill")->mValue.getInteger();
|
int iBaseArmorSkill = world->getStore().get<ESM::GameSetting>().find("iBaseArmorSkill")->mValue.getInteger();
|
||||||
|
|
|
@ -507,23 +507,16 @@ namespace MWClass
|
||||||
|
|
||||||
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
float Creature::getSpeed(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
|
||||||
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
const GMST& gmst = getGmst();
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
float walkSpeed = gmst.fMinWalkSpeedCreature->mValue.getFloat() + 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
|
||||||
* (gmst.fMaxWalkSpeedCreature->mValue.getFloat() - gmst.fMinWalkSpeedCreature->mValue.getFloat());
|
|
||||||
|
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||||
|
|
||||||
bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run);
|
|
||||||
|
|
||||||
// The Run speed difference for creatures comes from the animation speed difference (see runStateToWalkState in character.cpp)
|
|
||||||
float runSpeed = walkSpeed;
|
|
||||||
|
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
|
|
||||||
if(getEncumbrance(ptr) > getCapacity(ptr))
|
if(getEncumbrance(ptr) > getCapacity(ptr))
|
||||||
|
@ -540,19 +533,9 @@ namespace MWClass
|
||||||
moveSpeed = flySpeed;
|
moveSpeed = flySpeed;
|
||||||
}
|
}
|
||||||
else if(world->isSwimming(ptr))
|
else if(world->isSwimming(ptr))
|
||||||
{
|
moveSpeed = getSwimSpeed(ptr);
|
||||||
float swimSpeed = walkSpeed;
|
|
||||||
if(running)
|
|
||||||
swimSpeed = runSpeed;
|
|
||||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
|
||||||
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
|
|
||||||
gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
|
||||||
moveSpeed = swimSpeed;
|
|
||||||
}
|
|
||||||
else if(running)
|
|
||||||
moveSpeed = runSpeed;
|
|
||||||
else
|
else
|
||||||
moveSpeed = walkSpeed;
|
moveSpeed = getWalkSpeed(ptr);
|
||||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
||||||
moveSpeed *= 0.75f;
|
moveSpeed *= 0.75f;
|
||||||
|
|
||||||
|
@ -605,7 +588,7 @@ namespace MWClass
|
||||||
float Creature::getCapacity (const MWWorld::Ptr& ptr) const
|
float Creature::getCapacity (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
|
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
|
||||||
return static_cast<float>(stats.getAttribute(ESM::Attribute::Strength).getModified() * 5);
|
return stats.getAttribute(ESM::Attribute::Strength).getModified() * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Creature::getServices(const MWWorld::ConstPtr &actor) const
|
int Creature::getServices(const MWWorld::ConstPtr &actor) const
|
||||||
|
@ -745,7 +728,7 @@ namespace MWClass
|
||||||
throw std::runtime_error(std::string("Unexpected soundgen type: ")+name);
|
throw std::runtime_error(std::string("Unexpected soundgen type: ")+name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Creature::getSkill(const MWWorld::Ptr &ptr, int skill) const
|
float Creature::getSkill(const MWWorld::Ptr &ptr, int skill) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
@ -809,6 +792,12 @@ namespace MWClass
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptr.getRefData().getCount() <= 0)
|
||||||
|
{
|
||||||
|
state.mHasCustomState = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
const CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();
|
||||||
ESM::CreatureState& creatureState = state.asCreatureState();
|
ESM::CreatureState& creatureState = state.asCreatureState();
|
||||||
customData.mContainerStore->writeState (creatureState.mInventory);
|
customData.mContainerStore->writeState (creatureState.mInventory);
|
||||||
|
@ -878,4 +867,36 @@ namespace MWClass
|
||||||
const MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
const MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
scale *= ref->mBase->mScale;
|
scale *= ref->mBase->mScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Creature::setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const
|
||||||
|
{
|
||||||
|
MWMechanics::setBaseAISetting<ESM::Creature>(id, setting, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Creature::getWalkSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
|
return gmst.fMinWalkSpeedCreature->mValue.getFloat()
|
||||||
|
+ 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||||
|
* (gmst.fMaxWalkSpeedCreature->mValue.getFloat() - gmst.fMinWalkSpeedCreature->mValue.getFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
float Creature::getRunSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
return getWalkSpeed(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Creature::getSwimSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
const MWMechanics::MagicEffects& mageffects = stats.getMagicEffects();
|
||||||
|
|
||||||
|
return getWalkSpeed(ptr)
|
||||||
|
* (1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude())
|
||||||
|
* (gmst.fSwimRunBase->mValue.getFloat()
|
||||||
|
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace MWClass
|
||||||
virtual bool canSwim (const MWWorld::ConstPtr &ptr) const;
|
virtual bool canSwim (const MWWorld::ConstPtr &ptr) const;
|
||||||
virtual bool canWalk (const MWWorld::ConstPtr &ptr) const;
|
virtual bool canWalk (const MWWorld::ConstPtr &ptr) const;
|
||||||
|
|
||||||
virtual int getSkill(const MWWorld::Ptr &ptr, int skill) const;
|
virtual float getSkill(const MWWorld::Ptr &ptr, int skill) const;
|
||||||
|
|
||||||
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
||||||
virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const;
|
virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const;
|
||||||
|
@ -129,6 +129,14 @@ namespace MWClass
|
||||||
|
|
||||||
virtual void adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const;
|
virtual void adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const;
|
||||||
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
|
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
|
||||||
|
|
||||||
|
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||||
|
|
||||||
|
float getWalkSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
|
|
||||||
|
float getRunSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
|
|
||||||
|
float getSwimSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
int alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy);
|
float alchemySkill = player.getClass().getSkill(player, ESM::Skill::Alchemy);
|
||||||
|
|
||||||
static const float fWortChanceValue =
|
static const float fWortChanceValue =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->mValue.getFloat();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->mValue.getFloat();
|
||||||
|
|
|
@ -127,8 +127,8 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial health
|
// initial health
|
||||||
int strength = creatureStats.getAttribute(ESM::Attribute::Strength).getBase();
|
float strength = creatureStats.getAttribute(ESM::Attribute::Strength).getBase();
|
||||||
int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getBase();
|
float endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getBase();
|
||||||
|
|
||||||
int multiplier = 3;
|
int multiplier = 3;
|
||||||
|
|
||||||
|
@ -947,16 +947,6 @@ namespace MWClass
|
||||||
bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr);
|
bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr);
|
||||||
running = running && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr));
|
running = running && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr));
|
||||||
|
|
||||||
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
|
|
||||||
(gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
|
|
||||||
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat()*normalizedEncumbrance;
|
|
||||||
walkSpeed = std::max(0.0f, walkSpeed);
|
|
||||||
if(sneaking)
|
|
||||||
walkSpeed *= gmst.fSneakSpeedMultiplier->mValue.getFloat();
|
|
||||||
|
|
||||||
float runSpeed = walkSpeed*(0.01f * getSkill(ptr, ESM::Skill::Athletics) *
|
|
||||||
gmst.fAthleticsRunBonus->mValue.getFloat() + gmst.fBaseRunMultiplier->mValue.getFloat());
|
|
||||||
|
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(getEncumbrance(ptr) > getCapacity(ptr))
|
if(getEncumbrance(ptr) > getCapacity(ptr))
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
|
@ -971,19 +961,11 @@ namespace MWClass
|
||||||
moveSpeed = flySpeed;
|
moveSpeed = flySpeed;
|
||||||
}
|
}
|
||||||
else if (swimming)
|
else if (swimming)
|
||||||
{
|
moveSpeed = getSwimSpeed(ptr);
|
||||||
float swimSpeed = walkSpeed;
|
|
||||||
if(running)
|
|
||||||
swimSpeed = runSpeed;
|
|
||||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
|
||||||
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics)*
|
|
||||||
gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
|
||||||
moveSpeed = swimSpeed;
|
|
||||||
}
|
|
||||||
else if (running && !sneaking)
|
else if (running && !sneaking)
|
||||||
moveSpeed = runSpeed;
|
moveSpeed = getRunSpeed(ptr);
|
||||||
else
|
else
|
||||||
moveSpeed = walkSpeed;
|
moveSpeed = getWalkSpeed(ptr);
|
||||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
||||||
moveSpeed *= 0.75f;
|
moveSpeed *= 0.75f;
|
||||||
|
|
||||||
|
@ -1011,7 +993,7 @@ namespace MWClass
|
||||||
gmst.fJumpEncumbranceMultiplier->mValue.getFloat() *
|
gmst.fJumpEncumbranceMultiplier->mValue.getFloat() *
|
||||||
(1.0f - Npc::getNormalizedEncumbrance(ptr));
|
(1.0f - Npc::getNormalizedEncumbrance(ptr));
|
||||||
|
|
||||||
float a = static_cast<float>(getSkill(ptr, ESM::Skill::Acrobatics));
|
float a = getSkill(ptr, ESM::Skill::Acrobatics);
|
||||||
float b = 0.0f;
|
float b = 0.0f;
|
||||||
if(a > 50.0f)
|
if(a > 50.0f)
|
||||||
{
|
{
|
||||||
|
@ -1136,7 +1118,7 @@ namespace MWClass
|
||||||
|
|
||||||
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
|
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
|
||||||
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();
|
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();
|
||||||
int unarmoredSkill = getSkill(ptr, ESM::Skill::Unarmored);
|
float unarmoredSkill = getSkill(ptr, ESM::Skill::Unarmored);
|
||||||
|
|
||||||
float ratings[MWWorld::InventoryStore::Slots];
|
float ratings[MWWorld::InventoryStore::Slots];
|
||||||
for(int i = 0;i < MWWorld::InventoryStore::Slots;i++)
|
for(int i = 0;i < MWWorld::InventoryStore::Slots;i++)
|
||||||
|
@ -1283,7 +1265,7 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(cell.insert(ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const
|
float Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const
|
||||||
{
|
{
|
||||||
return getNpcStats(ptr).getSkill(skill).getModified();
|
return getNpcStats(ptr).getSkill(skill).getModified();
|
||||||
}
|
}
|
||||||
|
@ -1327,6 +1309,12 @@ namespace MWClass
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptr.getRefData().getCount() <= 0)
|
||||||
|
{
|
||||||
|
state.mHasCustomState = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
const NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();
|
||||||
ESM::NpcState& npcState = state.asNpcState();
|
ESM::NpcState& npcState = state.asNpcState();
|
||||||
customData.mInventoryStore.writeState (npcState.mInventory);
|
customData.mInventoryStore.writeState (npcState.mInventory);
|
||||||
|
@ -1437,4 +1425,61 @@ namespace MWClass
|
||||||
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||||
return ref->mBase->getFactionRank();
|
return ref->mBase->getFactionRank();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Npc::setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const
|
||||||
|
{
|
||||||
|
MWMechanics::setBaseAISetting<ESM::NPC>(id, setting, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Npc::getWalkSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
const NpcCustomData* npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||||
|
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||||
|
const bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr);
|
||||||
|
|
||||||
|
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat()
|
||||||
|
+ 0.01f * npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()
|
||||||
|
* (gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
|
||||||
|
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat()*normalizedEncumbrance;
|
||||||
|
walkSpeed = std::max(0.0f, walkSpeed);
|
||||||
|
if(sneaking)
|
||||||
|
walkSpeed *= gmst.fSneakSpeedMultiplier->mValue.getFloat();
|
||||||
|
|
||||||
|
return walkSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Npc::getRunSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
return getWalkSpeed(ptr)
|
||||||
|
* (0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fAthleticsRunBonus->mValue.getFloat()
|
||||||
|
+ gmst.fBaseRunMultiplier->mValue.getFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
float Npc::getSwimSpeed(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
const GMST& gmst = getGmst();
|
||||||
|
const MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
const MWMechanics::CreatureStats& stats = getCreatureStats(ptr);
|
||||||
|
const NpcCustomData* npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
|
||||||
|
const MWMechanics::MagicEffects& mageffects = npcdata->mNpcStats.getMagicEffects();
|
||||||
|
const bool swimming = world->isSwimming(ptr);
|
||||||
|
const bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr);
|
||||||
|
const bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run)
|
||||||
|
&& (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr));
|
||||||
|
|
||||||
|
float swimSpeed;
|
||||||
|
|
||||||
|
if (running)
|
||||||
|
swimSpeed = getRunSpeed(ptr);
|
||||||
|
else
|
||||||
|
swimSpeed = getWalkSpeed(ptr);
|
||||||
|
|
||||||
|
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
|
||||||
|
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat()
|
||||||
|
+ 0.01f * getSkill(ptr, ESM::Skill::Athletics) * gmst.fSwimRunAthleticsMult->mValue.getFloat();
|
||||||
|
|
||||||
|
return swimSpeed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace MWClass
|
||||||
|
|
||||||
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;
|
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;
|
||||||
|
|
||||||
virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const;
|
virtual float getSkill(const MWWorld::Ptr& ptr, int skill) const;
|
||||||
|
|
||||||
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
/// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
|
||||||
virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const;
|
virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const;
|
||||||
|
@ -164,6 +164,14 @@ namespace MWClass
|
||||||
|
|
||||||
virtual std::string getPrimaryFaction(const MWWorld::ConstPtr &ptr) const;
|
virtual std::string getPrimaryFaction(const MWWorld::ConstPtr &ptr) const;
|
||||||
virtual int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const;
|
virtual int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const;
|
||||||
|
|
||||||
|
virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const;
|
||||||
|
|
||||||
|
float getWalkSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
|
|
||||||
|
float getRunSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
|
|
||||||
|
float getSwimSpeed(const MWWorld::Ptr& ptr) const final;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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", "AttribVal6", "AttribVal7", "AttribVal8", 0
|
||||||
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
|
};
|
||||||
"AttribVal6", "AttribVal7", "AttribVal8",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i=0; ids[i]; ++i)
|
for (int i=0; ids[i]; ++i)
|
||||||
|
{
|
||||||
|
if (ids[i]==id)
|
||||||
{
|
{
|
||||||
if (ids[i]==id)
|
mPlayerAttributes[static_cast<ESM::Attribute::AttributeID>(i)] = value;
|
||||||
mReviewDialog->setAttribute(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->setMagicka( stats.getMagicka() );
|
|
||||||
mReviewDialog->setFatigue( stats.getFatigue() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mReviewDialog->setHealth(stats.getHealth());
|
||||||
|
mReviewDialog->setMagicka(stats.getMagicka());
|
||||||
|
mReviewDialog->setFatigue(stats.getFatigue());
|
||||||
|
for (auto& attributePair : mPlayerAttributes)
|
||||||
{
|
{
|
||||||
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (attributePair.first), attributePair.second);
|
||||||
for (auto& attributePair : attributes)
|
|
||||||
{
|
|
||||||
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();
|
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (skillPair.first), skillPair.second);
|
||||||
for (auto& skillPair : skills)
|
|
||||||
{
|
|
||||||
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;
|
||||||
|
|
|
@ -477,6 +477,8 @@ namespace MWGui
|
||||||
|
|
||||||
void DialogueWindow::onClose()
|
void DialogueWindow::onClose()
|
||||||
{
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Dialogue))
|
||||||
|
return;
|
||||||
// Reset history
|
// Reset history
|
||||||
for (DialogueText* text : mHistoryContents)
|
for (DialogueText* text : mHistoryContents)
|
||||||
delete text;
|
delete text;
|
||||||
|
|
|
@ -81,6 +81,12 @@ namespace MWGui
|
||||||
MWBase::Environment::get().getMechanicsManager()->rest(mDays * 24, true);
|
MWBase::Environment::get().getMechanicsManager()->rest(mDays * 24, true);
|
||||||
MWBase::Environment::get().getWorld()->advanceTime(mDays * 24);
|
MWBase::Environment::get().getWorld()->advanceTime(mDays * 24);
|
||||||
|
|
||||||
|
// We should not worsen corprus when in prison
|
||||||
|
for (auto& spell : player.getClass().getCreatureStats(player).getCorprusSpells())
|
||||||
|
{
|
||||||
|
spell.second.mNextWorsening += mDays * 24;
|
||||||
|
}
|
||||||
|
|
||||||
std::set<int> skills;
|
std::set<int> skills;
|
||||||
for (int day=0; day<mDays; ++day)
|
for (int day=0; day<mDays; ++day)
|
||||||
{
|
{
|
||||||
|
@ -89,9 +95,9 @@ namespace MWGui
|
||||||
|
|
||||||
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
|
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
|
||||||
if (skill == ESM::Skill::Security || skill == ESM::Skill::Sneak)
|
if (skill == ESM::Skill::Security || skill == ESM::Skill::Sneak)
|
||||||
value.setBase(std::min(100, value.getBase()+1));
|
value.setBase(std::min(100.f, value.getBase()+1));
|
||||||
else
|
else
|
||||||
value.setBase(std::max(0, value.getBase()-1));
|
value.setBase(std::max(0.f, value.getBase()-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace MWGui
|
||||||
mAttributeValues[i]->setEnabled(true);
|
mAttributeValues[i]->setEnabled(true);
|
||||||
availableAttributes++;
|
availableAttributes++;
|
||||||
|
|
||||||
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
float mult = pcStats.getLevelupAttributeMultiplier (i);
|
||||||
mult = std::min(mult, 100-pcStats.getAttribute(i).getBase());
|
mult = std::min(mult, 100-pcStats.getAttribute(i).getBase());
|
||||||
text->setCaption(mult <= 1 ? "" : "x" + MyGUI::utility::toString(mult));
|
text->setCaption(mult <= 1 ? "" : "x" + MyGUI::utility::toString(mult));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <components/myguiplatform/myguitexture.hpp>
|
#include <components/myguiplatform/myguitexture.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
@ -29,9 +30,9 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
LoadingScreen::LoadingScreen(const VFS::Manager* vfs, osgViewer::Viewer* viewer)
|
LoadingScreen::LoadingScreen(Resource::ResourceSystem* resourceSystem, osgViewer::Viewer* viewer)
|
||||||
: WindowBase("openmw_loading_screen.layout")
|
: WindowBase("openmw_loading_screen.layout")
|
||||||
, mVFS(vfs)
|
, mResourceSystem(resourceSystem)
|
||||||
, mViewer(viewer)
|
, mViewer(viewer)
|
||||||
, mTargetFrameRate(120.0)
|
, mTargetFrameRate(120.0)
|
||||||
, mLastWallpaperChangeTime(0.0)
|
, mLastWallpaperChangeTime(0.0)
|
||||||
|
@ -64,9 +65,9 @@ namespace MWGui
|
||||||
|
|
||||||
void LoadingScreen::findSplashScreens()
|
void LoadingScreen::findSplashScreens()
|
||||||
{
|
{
|
||||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
const std::map<std::string, VFS::File*>& index = mResourceSystem->getVFS()->getIndex();
|
||||||
std::string pattern = "Splash/";
|
std::string pattern = "Splash/";
|
||||||
mVFS->normalizeFilename(pattern);
|
mResourceSystem->getVFS()->normalizeFilename(pattern);
|
||||||
|
|
||||||
/* priority given to the left */
|
/* priority given to the left */
|
||||||
const std::array<std::string, 7> supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}};
|
const std::array<std::string, 7> supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}};
|
||||||
|
@ -171,6 +172,11 @@ namespace MWGui
|
||||||
// We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound()
|
// We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound()
|
||||||
mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback);
|
mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback);
|
||||||
|
|
||||||
|
if (const osgUtil::IncrementalCompileOperation* ico = mViewer->getIncrementalCompileOperation()) {
|
||||||
|
mOldIcoMin = ico->getMinimumTimeAvailableForGLCompileAndDeletePerFrame();
|
||||||
|
mOldIcoMax = ico->getMaximumNumOfObjectsToCompilePerFrame();
|
||||||
|
}
|
||||||
|
|
||||||
mVisible = visible;
|
mVisible = visible;
|
||||||
mLoadingBox->setVisible(mVisible);
|
mLoadingBox->setVisible(mVisible);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
@ -215,6 +221,12 @@ namespace MWGui
|
||||||
//std::cout << "loading took " << mTimer.time_m() - mLoadingOnTime << std::endl;
|
//std::cout << "loading took " << mTimer.time_m() - mLoadingOnTime << std::endl;
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
|
||||||
|
if (osgUtil::IncrementalCompileOperation* ico = mViewer->getIncrementalCompileOperation())
|
||||||
|
{
|
||||||
|
ico->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(mOldIcoMin);
|
||||||
|
ico->setMaximumNumOfObjectsToCompilePerFrame(mOldIcoMax);
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper);
|
||||||
}
|
}
|
||||||
|
@ -336,7 +348,13 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
||||||
|
|
||||||
//osg::Timer timer;
|
mResourceSystem->reportStats(mViewer->getFrameStamp()->getFrameNumber(), mViewer->getViewerStats());
|
||||||
|
if (osgUtil::IncrementalCompileOperation* ico = mViewer->getIncrementalCompileOperation())
|
||||||
|
{
|
||||||
|
ico->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(1.f/getTargetFrameRate());
|
||||||
|
ico->setMaximumNumOfObjectsToCompilePerFrame(1000);
|
||||||
|
}
|
||||||
|
|
||||||
// at the time this function is called we are in the middle of a frame,
|
// at the time this function is called we are in the middle of a frame,
|
||||||
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
// so out of order calls are necessary to get a correct frameNumber for the next frame.
|
||||||
// refer to the advance() and frame() order in Engine::go()
|
// refer to the advance() and frame() order in Engine::go()
|
||||||
|
@ -344,10 +362,6 @@ namespace MWGui
|
||||||
mViewer->updateTraversal();
|
mViewer->updateTraversal();
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||||
//std::cout << "frame took " << timer.time_m() << std::endl;
|
|
||||||
|
|
||||||
//if (mViewer->getIncrementalCompileOperation())
|
|
||||||
//std::cout << "num to compile " << mViewer->getIncrementalCompileOperation()->getToCompile().size() << std::endl;
|
|
||||||
|
|
||||||
mLastRenderTime = mTimer.time_m();
|
mLastRenderTime = mTimer.time_m();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ namespace osg
|
||||||
class Texture2D;
|
class Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace VFS
|
namespace Resource
|
||||||
{
|
{
|
||||||
class Manager;
|
class ResourceSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -32,7 +32,7 @@ namespace MWGui
|
||||||
class LoadingScreen : public WindowBase, public Loading::Listener
|
class LoadingScreen : public WindowBase, public Loading::Listener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LoadingScreen(const VFS::Manager* vfs, osgViewer::Viewer* viewer);
|
LoadingScreen(Resource::ResourceSystem* resourceSystem, osgViewer::Viewer* viewer);
|
||||||
virtual ~LoadingScreen();
|
virtual ~LoadingScreen();
|
||||||
|
|
||||||
/// Overridden from Loading::Listener, see the Loading::Listener documentation for usage details
|
/// Overridden from Loading::Listener, see the Loading::Listener documentation for usage details
|
||||||
|
@ -53,7 +53,7 @@ namespace MWGui
|
||||||
|
|
||||||
void setupCopyFramebufferToTextureCallback();
|
void setupCopyFramebufferToTextureCallback();
|
||||||
|
|
||||||
const VFS::Manager* mVFS;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
|
|
||||||
double mTargetFrameRate;
|
double mTargetFrameRate;
|
||||||
|
@ -70,6 +70,8 @@ namespace MWGui
|
||||||
size_t mProgress;
|
size_t mProgress;
|
||||||
|
|
||||||
bool mShowWallpaper;
|
bool mShowWallpaper;
|
||||||
|
float mOldIcoMin = 0.f;
|
||||||
|
unsigned int mOldIcoMax = 0;
|
||||||
|
|
||||||
MyGUI::Widget* mLoadingBox;
|
MyGUI::Widget* mLoadingBox;
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,7 @@ namespace MWGui
|
||||||
MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
|
MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
|
||||||
MyGUI::Align::Top | MyGUI::Align::Left);
|
MyGUI::Align::Top | MyGUI::Align::Left);
|
||||||
fog->setDepth(Local_FogLayer);
|
fog->setDepth(Local_FogLayer);
|
||||||
|
fog->setColour(MyGUI::Colour(0, 0, 0));
|
||||||
|
|
||||||
map->setNeedMouseFocus(false);
|
map->setNeedMouseFocus(false);
|
||||||
fog->setNeedMouseFocus(false);
|
fog->setNeedMouseFocus(false);
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
mSourceModel = sourceModel;
|
mSourceModel = sourceModel;
|
||||||
int chance = player.getClass().getSkill(player, ESM::Skill::Sneak);
|
float chance = player.getClass().getSkill(player, ESM::Skill::Sneak);
|
||||||
|
|
||||||
mSourceModel->update();
|
mSourceModel->update();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
|
||||||
#include "../mwmechanics/spells.hpp"
|
#include "../mwmechanics/spells.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
|
|
||||||
#include "tooltips.hpp"
|
#include "tooltips.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
#include "../mwmechanics/spells.hpp"
|
#include "../mwmechanics/spells.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
|
@ -159,7 +159,7 @@ namespace MWGui
|
||||||
for (int i=0; ids[i]; ++i)
|
for (int i=0; ids[i]; ++i)
|
||||||
if (ids[i]==id)
|
if (ids[i]==id)
|
||||||
{
|
{
|
||||||
setText (id, std::to_string(value.getModified()));
|
setText (id, std::to_string(static_cast<int>(value.getModified())));
|
||||||
|
|
||||||
MyGUI::TextBox* box;
|
MyGUI::TextBox* box;
|
||||||
getWidget(box, id);
|
getWidget(box, id);
|
||||||
|
|
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();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellutil.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
#include "mapwindow.hpp"
|
#include "mapwindow.hpp"
|
||||||
|
|
|
@ -74,11 +74,11 @@ namespace MWGui
|
||||||
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
mPlayerGold->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
||||||
|
|
||||||
// NPC can train you in his best 3 skills
|
// NPC can train you in his best 3 skills
|
||||||
std::vector< std::pair<int, int> > skills;
|
std::vector< std::pair<int, float> > skills;
|
||||||
|
|
||||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
int value = actor.getClass().getSkill(actor, i);
|
float value = actor.getClass().getSkill(actor, i);
|
||||||
|
|
||||||
skills.push_back(std::make_pair(i, value));
|
skills.push_back(std::make_pair(i, value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,11 +150,10 @@ namespace MWGui
|
||||||
if (hour >= 13) hour -= 12;
|
if (hour >= 13) hour -= 12;
|
||||||
if (hour == 0) hour = 12;
|
if (hour == 0) hour = 12;
|
||||||
|
|
||||||
std::string dateTimeText =
|
ESM::EpochTimeStamp currentDate = MWBase::Environment::get().getWorld()->getEpochTimeStamp();
|
||||||
MyGUI::utility::toString(MWBase::Environment::get().getWorld ()->getDay ()) + " "
|
int daysPassed = MWBase::Environment::get().getWorld()->getTimeStamp().getDay();
|
||||||
+ month + " (#{sDay} " + MyGUI::utility::toString(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay())
|
std::string formattedHour = pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}";
|
||||||
+ ") " + MyGUI::utility::toString(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
|
std::string dateTimeText = Misc::StringUtils::format("%i %s (#{sDay} %i) %i %s", currentDate.mDay, month, daysPassed, hour, formattedHour);
|
||||||
|
|
||||||
mDateTimeText->setCaptionWithReplacing (dateTimeText);
|
mDateTimeText->setCaptionWithReplacing (dateTimeText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,12 +15,16 @@
|
||||||
#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>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/sdlutil/sdlcursormanager.hpp>
|
#include <components/sdlutil/sdlcursormanager.hpp>
|
||||||
|
#include <components/sdlutil/sdlvideowrapper.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
@ -113,21 +117,10 @@
|
||||||
#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(
|
||||||
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,
|
||||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath)
|
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath)
|
||||||
: mOldUpdateMask(0)
|
: mOldUpdateMask(0)
|
||||||
|
@ -178,12 +171,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)
|
||||||
|
@ -194,8 +181,8 @@ namespace MWGui
|
||||||
, mRestAllowed(true)
|
, mRestAllowed(true)
|
||||||
, mShowOwned(0)
|
, mShowOwned(0)
|
||||||
, mEncoding(encoding)
|
, mEncoding(encoding)
|
||||||
, mFontHeight(16)
|
|
||||||
, mVersionDescription(versionDescription)
|
, mVersionDescription(versionDescription)
|
||||||
|
, mWindowVisible(true)
|
||||||
{
|
{
|
||||||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), uiScale);
|
mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), uiScale);
|
||||||
|
@ -231,13 +218,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");
|
||||||
|
@ -250,7 +230,7 @@ namespace MWGui
|
||||||
mKeyboardNavigation->setEnabled(keyboardNav);
|
mKeyboardNavigation->setEnabled(keyboardNav);
|
||||||
Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav);
|
Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav);
|
||||||
|
|
||||||
mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer);
|
mLoadingScreen = new LoadingScreen(mResourceSystem, mViewer);
|
||||||
mWindows.push_back(mLoadingScreen);
|
mWindows.push_back(mLoadingScreen);
|
||||||
|
|
||||||
//set up the hardware cursor manager
|
//set up the hardware cursor manager
|
||||||
|
@ -288,94 +268,10 @@ namespace MWGui
|
||||||
MyGUI::ClipboardManager::getInstance().eventClipboardRequested += MyGUI::newDelegate(this, &WindowManager::onClipboardRequested);
|
MyGUI::ClipboardManager::getInstance().eventClipboardRequested += MyGUI::newDelegate(this, &WindowManager::onClipboardRequested);
|
||||||
|
|
||||||
mShowOwned = Settings::Manager::getInt("show owned", "Game");
|
mShowOwned = Settings::Manager::getInt("show owned", "Game");
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::loadFontDelegate(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version)
|
mVideoWrapper = new SDLUtil::VideoWrapper(window, viewer);
|
||||||
{
|
mVideoWrapper->setGammaContrast(Settings::Manager::getFloat("gamma", "Video"),
|
||||||
MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator();
|
Settings::Manager::getFloat("contrast", "Video"));
|
||||||
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()
|
||||||
|
@ -389,26 +285,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();
|
||||||
|
|
||||||
|
@ -585,17 +462,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
|
||||||
|
@ -604,7 +470,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)
|
||||||
|
@ -625,7 +491,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();
|
||||||
|
@ -653,6 +518,7 @@ namespace MWGui
|
||||||
|
|
||||||
mGuiPlatform->shutdown();
|
mGuiPlatform->shutdown();
|
||||||
delete mGuiPlatform;
|
delete mGuiPlatform;
|
||||||
|
delete mVideoWrapper;
|
||||||
}
|
}
|
||||||
catch(const MyGUI::Exception& e)
|
catch(const MyGUI::Exception& e)
|
||||||
{
|
{
|
||||||
|
@ -787,40 +653,14 @@ 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)
|
||||||
{
|
{
|
||||||
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
||||||
/// 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)
|
||||||
|
@ -833,10 +673,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)
|
||||||
|
@ -858,8 +694,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()
|
||||||
|
@ -916,7 +750,7 @@ namespace MWGui
|
||||||
mMessageBoxManager->onFrame(dt);
|
mMessageBoxManager->onFrame(dt);
|
||||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
if (!mWindowVisible)
|
||||||
OpenThreads::Thread::microSleep(5000);
|
OpenThreads::Thread::microSleep(5000);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -995,7 +829,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;
|
||||||
|
@ -1241,6 +1075,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
|
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
|
||||||
|
|
||||||
|
bool changeRes = false;
|
||||||
for (const auto& setting : changed)
|
for (const auto& setting : changed)
|
||||||
{
|
{
|
||||||
if (setting.first == "HUD" && setting.second == "crosshair")
|
if (setting.first == "HUD" && setting.second == "crosshair")
|
||||||
|
@ -1249,11 +1084,38 @@ namespace MWGui
|
||||||
mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI");
|
mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI");
|
||||||
else if (setting.first == "GUI" && setting.second == "menu transparency")
|
else if (setting.first == "GUI" && setting.second == "menu transparency")
|
||||||
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
|
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
|
||||||
|
else if (setting.first == "Video" && (
|
||||||
|
setting.second == "resolution x"
|
||||||
|
|| setting.second == "resolution y"
|
||||||
|
|| setting.second == "fullscreen"
|
||||||
|
|| setting.second == "window border"))
|
||||||
|
changeRes = true;
|
||||||
|
|
||||||
|
else if (setting.first == "Video" && setting.second == "vsync")
|
||||||
|
mVideoWrapper->setSyncToVBlank(Settings::Manager::getBool("vsync", "Video"));
|
||||||
|
else if (setting.first == "Video" && (setting.second == "gamma" || setting.second == "contrast"))
|
||||||
|
mVideoWrapper->setGammaContrast(Settings::Manager::getFloat("gamma", "Video"),
|
||||||
|
Settings::Manager::getFloat("contrast", "Video"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeRes)
|
||||||
|
{
|
||||||
|
mVideoWrapper->setVideoMode(Settings::Manager::getInt("resolution x", "Video"),
|
||||||
|
Settings::Manager::getInt("resolution y", "Video"),
|
||||||
|
Settings::Manager::getBool("fullscreen", "Video"),
|
||||||
|
Settings::Manager::getBool("window border", "Video"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::windowResized(int x, int y)
|
void WindowManager::windowResized(int x, int y)
|
||||||
{
|
{
|
||||||
|
// Note: this is a side effect of resolution change or window resize.
|
||||||
|
// There is no need to track these changes.
|
||||||
|
Settings::Manager::setInt("resolution x", "Video", x);
|
||||||
|
Settings::Manager::setInt("resolution y", "Video", y);
|
||||||
|
Settings::Manager::resetPendingChange("resolution x", "Video");
|
||||||
|
Settings::Manager::resetPendingChange("resolution y", "Video");
|
||||||
|
|
||||||
mGuiPlatform->getRenderManagerPtr()->setViewSize(x, y);
|
mGuiPlatform->getRenderManagerPtr()->setViewSize(x, y);
|
||||||
|
|
||||||
// scaled size
|
// scaled size
|
||||||
|
@ -1283,9 +1145,27 @@ namespace MWGui
|
||||||
for (WindowBase* window : mWindows)
|
for (WindowBase* window : mWindows)
|
||||||
window->onResChange(x, y);
|
window->onResChange(x, y);
|
||||||
|
|
||||||
|
// We should reload TrueType fonts to fit new resolution
|
||||||
|
loadUserFonts();
|
||||||
|
|
||||||
// TODO: check if any windows are now off-screen and move them back if so
|
// TODO: check if any windows are now off-screen and move them back if so
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowManager::isWindowVisible()
|
||||||
|
{
|
||||||
|
return mWindowVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::windowVisibilityChange(bool visible)
|
||||||
|
{
|
||||||
|
mWindowVisible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::windowClosed()
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::onCursorChange(const std::string &name)
|
void WindowManager::onCursorChange(const std::string &name)
|
||||||
{
|
{
|
||||||
mCursorManager->cursorChanged(name);
|
mCursorManager->cursorChanged(name);
|
||||||
|
@ -1583,26 +1463,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);
|
||||||
|
@ -1925,7 +1785,7 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getInputManager()->isWindowVisible())
|
if (!mWindowVisible)
|
||||||
{
|
{
|
||||||
mVideoWidget->pause();
|
mVideoWidget->pause();
|
||||||
OpenThreads::Thread::microSleep(5000);
|
OpenThreads::Thread::microSleep(5000);
|
||||||
|
@ -2149,7 +2009,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)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ namespace SceneUtil
|
||||||
namespace SDLUtil
|
namespace SDLUtil
|
||||||
{
|
{
|
||||||
class SDLCursorManager;
|
class SDLCursorManager;
|
||||||
|
class VideoWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace osgMyGUI
|
namespace osgMyGUI
|
||||||
|
@ -124,13 +126,14 @@ namespace MWGui
|
||||||
class JailScreen;
|
class JailScreen;
|
||||||
class KeyboardNavigation;
|
class KeyboardNavigation;
|
||||||
|
|
||||||
class WindowManager : public MWBase::WindowManager
|
class WindowManager :
|
||||||
|
public MWBase::WindowManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::pair<std::string, int> Faction;
|
typedef std::pair<std::string, int> Faction;
|
||||||
typedef std::vector<Faction> FactionList;
|
typedef std::vector<Faction> FactionList;
|
||||||
|
|
||||||
WindowManager(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||||
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
|
||||||
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath);
|
ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath);
|
||||||
virtual ~WindowManager();
|
virtual ~WindowManager();
|
||||||
|
@ -277,13 +280,7 @@ namespace MWGui
|
||||||
|
|
||||||
virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
|
||||||
|
|
||||||
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
|
||||||
|
@ -296,7 +293,10 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
|
virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
virtual void windowVisibilityChange(bool visible);
|
||||||
virtual void windowResized(int x, int y);
|
virtual void windowResized(int x, int y);
|
||||||
|
virtual void windowClosed();
|
||||||
|
virtual bool isWindowVisible();
|
||||||
|
|
||||||
virtual void executeInConsole (const std::string& path);
|
virtual void executeInConsole (const std::string& path);
|
||||||
|
|
||||||
|
@ -411,8 +411,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).
|
||||||
|
@ -468,14 +466,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
|
||||||
|
@ -525,14 +515,16 @@ namespace MWGui
|
||||||
|
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
|
|
||||||
int mFontHeight;
|
|
||||||
|
|
||||||
std::string mVersionDescription;
|
std::string mVersionDescription;
|
||||||
|
|
||||||
|
bool mWindowVisible;
|
||||||
|
|
||||||
MWGui::TextColours mTextColours;
|
MWGui::TextColours mTextColours;
|
||||||
|
|
||||||
std::unique_ptr<KeyboardNavigation> mKeyboardNavigation;
|
std::unique_ptr<KeyboardNavigation> mKeyboardNavigation;
|
||||||
|
|
||||||
|
SDLUtil::VideoWrapper* mVideoWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when MyGUI tries to retrieve a tag's value. Tags must be denoted in #{tag} notation and will be replaced upon setting a user visible text/property.
|
* Called when MyGUI tries to retrieve a tag's value. Tags must be denoted in #{tag} notation and will be replaced upon setting a user visible text/property.
|
||||||
* Supported syntax:
|
* Supported syntax:
|
||||||
|
|
616
apps/openmw/mwinput/actionmanager.cpp
Normal file
616
apps/openmw/mwinput/actionmanager.cpp
Normal file
|
@ -0,0 +1,616 @@
|
||||||
|
#include "actionmanager.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
|
||||||
|
#include <SDL_keyboard.h>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
#include "bindingsmanager.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
const float ZOOM_SCALE = 120.f; /// Used for scrolling camera in and out
|
||||||
|
|
||||||
|
ActionManager::ActionManager(BindingsManager* bindingsManager,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
|
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||||
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler)
|
||||||
|
: mBindingsManager(bindingsManager)
|
||||||
|
, mViewer(viewer)
|
||||||
|
, mScreenCaptureHandler(screenCaptureHandler)
|
||||||
|
, mScreenCaptureOperation(screenCaptureOperation)
|
||||||
|
, mAlwaysRunActive(Settings::Manager::getBool("always run", "Input"))
|
||||||
|
, mSneaking(false)
|
||||||
|
, mAttemptJump(false)
|
||||||
|
, mOverencumberedMessageDelay(0.f)
|
||||||
|
, mPreviewPOVDelay(0.f)
|
||||||
|
, mTimeIdle(0.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::update(float dt, bool triedToMove)
|
||||||
|
{
|
||||||
|
// Disable movement in Gui mode
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()
|
||||||
|
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)
|
||||||
|
{
|
||||||
|
mAttemptJump = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure player movement according to keyboard input. Actual movement will
|
||||||
|
// be done in the physics system.
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
bool alwaysRunAllowed = false;
|
||||||
|
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
|
||||||
|
if (mBindingsManager->actionIsActive(A_MoveLeft) != mBindingsManager->actionIsActive(A_MoveRight))
|
||||||
|
{
|
||||||
|
alwaysRunAllowed = true;
|
||||||
|
triedToMove = true;
|
||||||
|
player.setLeftRight(mBindingsManager->actionIsActive(A_MoveRight) ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBindingsManager->actionIsActive(A_MoveForward) != mBindingsManager->actionIsActive(A_MoveBackward))
|
||||||
|
{
|
||||||
|
alwaysRunAllowed = true;
|
||||||
|
triedToMove = true;
|
||||||
|
player.setAutoMove (false);
|
||||||
|
player.setForwardBackward(mBindingsManager->actionIsActive(A_MoveForward) ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.getAutoMove())
|
||||||
|
{
|
||||||
|
alwaysRunAllowed = true;
|
||||||
|
triedToMove = true;
|
||||||
|
player.setForwardBackward (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAttemptJump && MWBase::Environment::get().getInputManager()->getControlSwitch("playerjumping"))
|
||||||
|
{
|
||||||
|
player.setUpDown(1);
|
||||||
|
triedToMove = true;
|
||||||
|
mOverencumberedMessageDelay = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
|
||||||
|
if (triedToMove)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
|
mOverencumberedMessageDelay -= dt;
|
||||||
|
if (playerPtr.getClass().getEncumbrance(playerPtr) > playerPtr.getClass().getCapacity(playerPtr))
|
||||||
|
{
|
||||||
|
player.setAutoMove (false);
|
||||||
|
if (mOverencumberedMessageDelay <= 0)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage59}");
|
||||||
|
mOverencumberedMessageDelay = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch"))
|
||||||
|
{
|
||||||
|
if (mBindingsManager->actionIsActive(A_TogglePOV))
|
||||||
|
{
|
||||||
|
if (mPreviewPOVDelay <= 0.5 &&
|
||||||
|
(mPreviewPOVDelay += dt) > 0.5)
|
||||||
|
{
|
||||||
|
mPreviewPOVDelay = 1.f;
|
||||||
|
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//disable preview mode
|
||||||
|
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
|
||||||
|
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->togglePOV();
|
||||||
|
}
|
||||||
|
mPreviewPOVDelay = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triedToMove)
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
|
||||||
|
static const bool isToggleSneak = Settings::Manager::getBool("toggle sneak", "Input");
|
||||||
|
if (!isToggleSneak)
|
||||||
|
{
|
||||||
|
if(!MWBase::Environment::get().getInputManager()->joystickLastUsed())
|
||||||
|
player.setSneak(mBindingsManager->actionIsActive(A_Sneak));
|
||||||
|
}
|
||||||
|
|
||||||
|
float xAxis = mBindingsManager->getActionValue(A_MoveLeftRight);
|
||||||
|
float yAxis = mBindingsManager->getActionValue(A_MoveForwardBackward);
|
||||||
|
bool isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25;
|
||||||
|
if ((mAlwaysRunActive && alwaysRunAllowed) || isRunning)
|
||||||
|
player.setRunState(!mBindingsManager->actionIsActive(A_Run));
|
||||||
|
else
|
||||||
|
player.setRunState(mBindingsManager->actionIsActive(A_Run));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBindingsManager->actionIsActive(A_MoveForward) ||
|
||||||
|
mBindingsManager->actionIsActive(A_MoveBackward) ||
|
||||||
|
mBindingsManager->actionIsActive(A_MoveLeft) ||
|
||||||
|
mBindingsManager->actionIsActive(A_MoveRight) ||
|
||||||
|
mBindingsManager->actionIsActive(A_Jump) ||
|
||||||
|
mBindingsManager->actionIsActive(A_Sneak) ||
|
||||||
|
mBindingsManager->actionIsActive(A_TogglePOV) ||
|
||||||
|
mBindingsManager->actionIsActive(A_ZoomIn) ||
|
||||||
|
mBindingsManager->actionIsActive(A_ZoomOut))
|
||||||
|
{
|
||||||
|
resetIdleTime();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateIdleTime(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
mAttemptJump = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::resetIdleTime()
|
||||||
|
{
|
||||||
|
if (mTimeIdle < 0)
|
||||||
|
MWBase::Environment::get().getWorld()->toggleVanityMode(false);
|
||||||
|
mTimeIdle = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::updateIdleTime(float dt)
|
||||||
|
{
|
||||||
|
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
|
.find("fVanityDelay")->mValue.getFloat();
|
||||||
|
if (mTimeIdle >= 0.f)
|
||||||
|
mTimeIdle += dt;
|
||||||
|
if (mTimeIdle > vanityDelay)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||||
|
mTimeIdle = -1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::executeAction(int action)
|
||||||
|
{
|
||||||
|
// trigger action activated
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case A_GameMenu:
|
||||||
|
toggleMainMenu ();
|
||||||
|
break;
|
||||||
|
case A_Screenshot:
|
||||||
|
screenshot();
|
||||||
|
break;
|
||||||
|
case A_Inventory:
|
||||||
|
toggleInventory ();
|
||||||
|
break;
|
||||||
|
case A_Console:
|
||||||
|
toggleConsole ();
|
||||||
|
break;
|
||||||
|
case A_Activate:
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
activate();
|
||||||
|
break;
|
||||||
|
case A_MoveLeft:
|
||||||
|
case A_MoveRight:
|
||||||
|
case A_MoveForward:
|
||||||
|
case A_MoveBackward:
|
||||||
|
handleGuiArrowKey(action);
|
||||||
|
break;
|
||||||
|
case A_Journal:
|
||||||
|
toggleJournal();
|
||||||
|
break;
|
||||||
|
case A_AutoMove:
|
||||||
|
toggleAutoMove();
|
||||||
|
break;
|
||||||
|
case A_AlwaysRun:
|
||||||
|
toggleWalking();
|
||||||
|
break;
|
||||||
|
case A_ToggleWeapon:
|
||||||
|
toggleWeapon();
|
||||||
|
break;
|
||||||
|
case A_Rest:
|
||||||
|
rest();
|
||||||
|
break;
|
||||||
|
case A_ToggleSpell:
|
||||||
|
toggleSpell();
|
||||||
|
break;
|
||||||
|
case A_QuickKey1:
|
||||||
|
quickKey(1);
|
||||||
|
break;
|
||||||
|
case A_QuickKey2:
|
||||||
|
quickKey(2);
|
||||||
|
break;
|
||||||
|
case A_QuickKey3:
|
||||||
|
quickKey(3);
|
||||||
|
break;
|
||||||
|
case A_QuickKey4:
|
||||||
|
quickKey(4);
|
||||||
|
break;
|
||||||
|
case A_QuickKey5:
|
||||||
|
quickKey(5);
|
||||||
|
break;
|
||||||
|
case A_QuickKey6:
|
||||||
|
quickKey(6);
|
||||||
|
break;
|
||||||
|
case A_QuickKey7:
|
||||||
|
quickKey(7);
|
||||||
|
break;
|
||||||
|
case A_QuickKey8:
|
||||||
|
quickKey(8);
|
||||||
|
break;
|
||||||
|
case A_QuickKey9:
|
||||||
|
quickKey(9);
|
||||||
|
break;
|
||||||
|
case A_QuickKey10:
|
||||||
|
quickKey(10);
|
||||||
|
break;
|
||||||
|
case A_QuickKeysMenu:
|
||||||
|
showQuickKeysMenu();
|
||||||
|
break;
|
||||||
|
case A_ToggleHUD:
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleHud();
|
||||||
|
break;
|
||||||
|
case A_ToggleDebug:
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
|
||||||
|
break;
|
||||||
|
case A_ZoomIn:
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
MWBase::Environment::get().getWorld()->setCameraDistance(ZOOM_SCALE, true, true);
|
||||||
|
break;
|
||||||
|
case A_ZoomOut:
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
MWBase::Environment::get().getWorld()->setCameraDistance(-ZOOM_SCALE, true, true);
|
||||||
|
break;
|
||||||
|
case A_QuickSave:
|
||||||
|
quickSave();
|
||||||
|
break;
|
||||||
|
case A_QuickLoad:
|
||||||
|
quickLoad();
|
||||||
|
break;
|
||||||
|
case A_CycleSpellLeft:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
|
||||||
|
break;
|
||||||
|
case A_CycleSpellRight:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponLeft:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponRight:
|
||||||
|
if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
|
||||||
|
break;
|
||||||
|
case A_Sneak:
|
||||||
|
static const bool isToggleSneak = Settings::Manager::getBool("toggle sneak", "Input");
|
||||||
|
if (isToggleSneak)
|
||||||
|
{
|
||||||
|
toggleSneaking();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ActionManager::checkAllowedToUseItems() const
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
if (player.getClass().getNpcStats(player).isWerewolf())
|
||||||
|
{
|
||||||
|
// Cannot use items or spells while in werewolf form
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::screenshot()
|
||||||
|
{
|
||||||
|
bool regularScreenshot = true;
|
||||||
|
|
||||||
|
std::string settingStr;
|
||||||
|
|
||||||
|
settingStr = Settings::Manager::getString("screenshot type","Video");
|
||||||
|
regularScreenshot = settingStr.size() == 0 || settingStr.compare("regular") == 0;
|
||||||
|
|
||||||
|
if (regularScreenshot)
|
||||||
|
{
|
||||||
|
mScreenCaptureHandler->setFramesToCapture(1);
|
||||||
|
mScreenCaptureHandler->captureNextFrame(*mViewer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Image> screenshot (new osg::Image);
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWorld()->screenshot360(screenshot.get(), settingStr))
|
||||||
|
{
|
||||||
|
(*mScreenCaptureOperation) (*(screenshot.get()), 0);
|
||||||
|
// FIXME: mScreenCaptureHandler->getCaptureOperation() causes crash for some reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleMainMenu()
|
||||||
|
{
|
||||||
|
if (MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleConsole();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) //No open GUIs, open up the MainMenu
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||||
|
}
|
||||||
|
else //Close current GUI
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleSpell()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
|
||||||
|
// Not allowed before the magic window is accessible
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playermagic") || !MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!checkAllowedToUseItems())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Not allowed if no spell selected
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
MWWorld::InventoryStore& inventory = player.getPlayer().getClass().getInventoryStore(player.getPlayer());
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->getSelectedSpell().empty() &&
|
||||||
|
inventory.getSelectedEnchantItem() == inventory.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player.getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWMechanics::DrawState_ state = player.getDrawState();
|
||||||
|
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
||||||
|
player.setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
else
|
||||||
|
player.setDrawState(MWMechanics::DrawState_Nothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::quickLoad()
|
||||||
|
{
|
||||||
|
if (!MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
MWBase::Environment::get().getStateManager()->quickLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::quickSave()
|
||||||
|
{
|
||||||
|
if (!MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
MWBase::Environment::get().getStateManager()->quickSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleWeapon()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
|
||||||
|
// Not allowed before the inventory window is accessible
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playerfighting") || !MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
// We want to interrupt animation only if attack is preparing, but still is not triggered
|
||||||
|
// Otherwise we will get a "speedshooting" exploit, when player can skip reload animation by hitting "Toggle Weapon" key twice
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackPreparing(player.getPlayer()))
|
||||||
|
player.setAttackingOrSpell(false);
|
||||||
|
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player.getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWMechanics::DrawState_ state = player.getDrawState();
|
||||||
|
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||||
|
player.setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
else
|
||||||
|
player.setDrawState(MWMechanics::DrawState_Nothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::rest()
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->getRestEnabled() || MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Rest); //Open rest GUI
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleInventory()
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Toggle between game mode and inventory mode
|
||||||
|
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
|
||||||
|
if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
|
||||||
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// .. but don't touch any other mode, except container.
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleConsole()
|
||||||
|
{
|
||||||
|
if (MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->toggleConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleJournal()
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
return;
|
||||||
|
if (MyGUI::InputManager::getInstance ().isModalAny())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Journal
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_MainMenu
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Settings
|
||||||
|
&& MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal);
|
||||||
|
}
|
||||||
|
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Journal))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Journal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::quickKey (int index)
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") || !MWBase::Environment::get().getInputManager()->getControlSwitch("playerfighting") || !MWBase::Environment::get().getInputManager()->getControlSwitch("playermagic"))
|
||||||
|
return;
|
||||||
|
if (!checkAllowedToUseItems())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")!=-1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
MWBase::Environment::get().getWindowManager()->activateQuickKey (index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::showQuickKeysMenu()
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode ()
|
||||||
|
&& MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")==-1)
|
||||||
|
{
|
||||||
|
if (!checkAllowedToUseItems())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_QuickKeysMenu);
|
||||||
|
}
|
||||||
|
else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu)
|
||||||
|
{
|
||||||
|
while (MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
{ //Handle any open Modal windows
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentModal();
|
||||||
|
}
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); //And handle the actual main window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::activate()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
{
|
||||||
|
bool joystickUsed = MWBase::Environment::get().getInputManager()->joystickLastUsed();
|
||||||
|
if (!SDL_IsTextInputActive() && !mBindingsManager->isLeftOrRightButton(A_Activate, joystickUsed))
|
||||||
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0, false);
|
||||||
|
}
|
||||||
|
else if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleAutoMove()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.setAutoMove (!player.getAutoMove());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleWalking()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode() || SDL_IsTextInputActive()) return;
|
||||||
|
mAlwaysRunActive = !mAlwaysRunActive;
|
||||||
|
|
||||||
|
Settings::Manager::setBool("always run", "Input", mAlwaysRunActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::toggleSneaking()
|
||||||
|
{
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols")) return;
|
||||||
|
mSneaking = !mSneaking;
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.setSneak(mSneaking);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionManager::handleGuiArrowKey(int action)
|
||||||
|
{
|
||||||
|
bool joystickUsed = MWBase::Environment::get().getInputManager()->joystickLastUsed();
|
||||||
|
// This is currently keyboard-specific code
|
||||||
|
// TODO: see if GUI controls can be refactored into a single function
|
||||||
|
if (joystickUsed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (SDL_IsTextInputActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mBindingsManager->isLeftOrRightButton(action, joystickUsed))
|
||||||
|
return;
|
||||||
|
|
||||||
|
MyGUI::KeyCode key;
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case A_MoveLeft:
|
||||||
|
key = MyGUI::KeyCode::ArrowLeft;
|
||||||
|
break;
|
||||||
|
case A_MoveRight:
|
||||||
|
key = MyGUI::KeyCode::ArrowRight;
|
||||||
|
break;
|
||||||
|
case A_MoveForward:
|
||||||
|
key = MyGUI::KeyCode::ArrowUp;
|
||||||
|
break;
|
||||||
|
case A_MoveBackward:
|
||||||
|
default:
|
||||||
|
key = MyGUI::KeyCode::ArrowDown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(key, 0, false);
|
||||||
|
}
|
||||||
|
}
|
78
apps/openmw/mwinput/actionmanager.hpp
Normal file
78
apps/openmw/mwinput/actionmanager.hpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef MWINPUT_ACTIONMANAGER_H
|
||||||
|
#define MWINPUT_ACTIONMANAGER_H
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
|
namespace osgViewer
|
||||||
|
{
|
||||||
|
class Viewer;
|
||||||
|
class ScreenCaptureHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class BindingsManager;
|
||||||
|
|
||||||
|
class ActionManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ActionManager(BindingsManager* bindingsManager,
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
|
||||||
|
osg::ref_ptr<osgViewer::Viewer> viewer,
|
||||||
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler);
|
||||||
|
|
||||||
|
void update(float dt, bool triedToMove);
|
||||||
|
|
||||||
|
void executeAction(int action);
|
||||||
|
|
||||||
|
bool checkAllowedToUseItems() const;
|
||||||
|
|
||||||
|
void toggleMainMenu();
|
||||||
|
void toggleSpell();
|
||||||
|
void toggleWeapon();
|
||||||
|
void toggleInventory();
|
||||||
|
void toggleConsole();
|
||||||
|
void screenshot();
|
||||||
|
void toggleJournal();
|
||||||
|
void activate();
|
||||||
|
void toggleWalking();
|
||||||
|
void toggleSneaking();
|
||||||
|
void toggleAutoMove();
|
||||||
|
void rest();
|
||||||
|
void quickLoad();
|
||||||
|
void quickSave();
|
||||||
|
|
||||||
|
void quickKey (int index);
|
||||||
|
void showQuickKeysMenu();
|
||||||
|
|
||||||
|
void resetIdleTime();
|
||||||
|
|
||||||
|
bool isAlwaysRunActive() const { return mAlwaysRunActive; };
|
||||||
|
bool isSneaking() const { return mSneaking; };
|
||||||
|
|
||||||
|
void setAttemptJump(bool enabled) { mAttemptJump = enabled; }
|
||||||
|
|
||||||
|
float getPreviewDelay() const { return mPreviewPOVDelay; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleGuiArrowKey(int action);
|
||||||
|
|
||||||
|
void updateIdleTime(float dt);
|
||||||
|
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||||
|
osgViewer::ScreenCaptureHandler::CaptureOperation* mScreenCaptureOperation;
|
||||||
|
|
||||||
|
bool mAlwaysRunActive;
|
||||||
|
bool mSneaking;
|
||||||
|
bool mAttemptJump;
|
||||||
|
|
||||||
|
float mOverencumberedMessageDelay;
|
||||||
|
float mPreviewPOVDelay;
|
||||||
|
float mTimeIdle;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
79
apps/openmw/mwinput/actions.hpp
Normal file
79
apps/openmw/mwinput/actions.hpp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef MWINPUT_ACTIONS_H
|
||||||
|
#define MWINPUT_ACTIONS_H
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
enum Actions
|
||||||
|
{
|
||||||
|
// please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files
|
||||||
|
|
||||||
|
A_GameMenu,
|
||||||
|
|
||||||
|
A_Unused,
|
||||||
|
|
||||||
|
A_Screenshot, // Take a screenshot
|
||||||
|
|
||||||
|
A_Inventory, // Toggle inventory screen
|
||||||
|
|
||||||
|
A_Console, // Toggle console screen
|
||||||
|
|
||||||
|
A_MoveLeft, // Move player left / right
|
||||||
|
A_MoveRight,
|
||||||
|
A_MoveForward, // Forward / Backward
|
||||||
|
A_MoveBackward,
|
||||||
|
|
||||||
|
A_Activate,
|
||||||
|
|
||||||
|
A_Use, //Use weapon, spell, etc.
|
||||||
|
A_Jump,
|
||||||
|
A_AutoMove, //Toggle Auto-move forward
|
||||||
|
A_Rest, //Rest
|
||||||
|
A_Journal, //Journal
|
||||||
|
A_Weapon, //Draw/Sheath weapon
|
||||||
|
A_Spell, //Ready/Unready Casting
|
||||||
|
A_Run, //Run when held
|
||||||
|
A_CycleSpellLeft, //cycling through spells
|
||||||
|
A_CycleSpellRight,
|
||||||
|
A_CycleWeaponLeft, //Cycling through weapons
|
||||||
|
A_CycleWeaponRight,
|
||||||
|
A_ToggleSneak, //Toggles Sneak
|
||||||
|
A_AlwaysRun, //Toggle Walking/Running
|
||||||
|
A_Sneak,
|
||||||
|
|
||||||
|
A_QuickSave,
|
||||||
|
A_QuickLoad,
|
||||||
|
A_QuickMenu,
|
||||||
|
A_ToggleWeapon,
|
||||||
|
A_ToggleSpell,
|
||||||
|
|
||||||
|
A_TogglePOV,
|
||||||
|
|
||||||
|
A_QuickKey1,
|
||||||
|
A_QuickKey2,
|
||||||
|
A_QuickKey3,
|
||||||
|
A_QuickKey4,
|
||||||
|
A_QuickKey5,
|
||||||
|
A_QuickKey6,
|
||||||
|
A_QuickKey7,
|
||||||
|
A_QuickKey8,
|
||||||
|
A_QuickKey9,
|
||||||
|
A_QuickKey10,
|
||||||
|
|
||||||
|
A_QuickKeysMenu,
|
||||||
|
|
||||||
|
A_ToggleHUD,
|
||||||
|
|
||||||
|
A_ToggleDebug,
|
||||||
|
|
||||||
|
A_LookUpDown, //Joystick look
|
||||||
|
A_LookLeftRight,
|
||||||
|
A_MoveForwardBackward,
|
||||||
|
A_MoveLeftRight,
|
||||||
|
|
||||||
|
A_ZoomIn,
|
||||||
|
A_ZoomOut,
|
||||||
|
|
||||||
|
A_Last // Marker for the last item
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
714
apps/openmw/mwinput/bindingsmanager.cpp
Normal file
714
apps/openmw/mwinput/bindingsmanager.cpp
Normal file
|
@ -0,0 +1,714 @@
|
||||||
|
#include "bindingsmanager.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
|
#include <extern/oics/ICSChannelListener.h>
|
||||||
|
#include <extern/oics/ICSInputControlSystem.h>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
#include "sdlmappings.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
static const int sFakeDeviceId = 1; //As we only support one controller at a time, use a fake deviceID so we don't lose bindings when switching controllers
|
||||||
|
|
||||||
|
void clearAllKeyBindings(ICS::InputControlSystem* inputBinder, ICS::Control* control)
|
||||||
|
{
|
||||||
|
// right now we don't really need multiple bindings for the same action, so remove all others first
|
||||||
|
if (inputBinder->getKeyBinding(control, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN)
|
||||||
|
inputBinder->removeKeyBinding(inputBinder->getKeyBinding(control, ICS::Control::INCREASE));
|
||||||
|
if (inputBinder->getMouseButtonBinding(control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS)
|
||||||
|
inputBinder->removeMouseButtonBinding(inputBinder->getMouseButtonBinding(control, ICS::Control::INCREASE));
|
||||||
|
if (inputBinder->getMouseWheelBinding(control, ICS::Control::INCREASE) != ICS::InputControlSystem::MouseWheelClick::UNASSIGNED)
|
||||||
|
inputBinder->removeMouseWheelBinding(inputBinder->getMouseWheelBinding(control, ICS::Control::INCREASE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearAllControllerBindings(ICS::InputControlSystem* inputBinder, ICS::Control* control)
|
||||||
|
{
|
||||||
|
// right now we don't really need multiple bindings for the same action, so remove all others first
|
||||||
|
if (inputBinder->getJoystickAxisBinding(control, sFakeDeviceId, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN)
|
||||||
|
inputBinder->removeJoystickAxisBinding(sFakeDeviceId, inputBinder->getJoystickAxisBinding(control, sFakeDeviceId, ICS::Control::INCREASE));
|
||||||
|
if (inputBinder->getJoystickButtonBinding(control, sFakeDeviceId, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS)
|
||||||
|
inputBinder->removeJoystickButtonBinding(sFakeDeviceId, inputBinder->getJoystickButtonBinding(control, sFakeDeviceId, ICS::Control::INCREASE));
|
||||||
|
}
|
||||||
|
|
||||||
|
class InputControlSystem : public ICS::InputControlSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InputControlSystem(const std::string& bindingsFile)
|
||||||
|
: ICS::InputControlSystem(bindingsFile, true, nullptr, nullptr, A_Last)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BindingsListener :
|
||||||
|
public ICS::ChannelListener,
|
||||||
|
public ICS::DetectingBindingListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BindingsListener(ICS::InputControlSystem* inputBinder, BindingsManager* bindingsManager)
|
||||||
|
: mInputBinder(inputBinder)
|
||||||
|
, mBindingsManager(bindingsManager)
|
||||||
|
, mDetectingKeyboard(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~BindingsListener() = default;
|
||||||
|
|
||||||
|
virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue)
|
||||||
|
{
|
||||||
|
int action = channel->getNumber();
|
||||||
|
mBindingsManager->actionValueChanged(action, currentValue, previousValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
||||||
|
, SDL_Scancode key, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
//Disallow binding escape key
|
||||||
|
if (key==SDL_SCANCODE_ESCAPE)
|
||||||
|
{
|
||||||
|
//Stop binding if esc pressed
|
||||||
|
mInputBinder->cancelDetectingBindingState();
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow binding reserved keys
|
||||||
|
if (key == SDL_SCANCODE_F3 || key == SDL_SCANCODE_F4 || key == SDL_SCANCODE_F10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
// Disallow binding Windows/Meta keys
|
||||||
|
if (key == SDL_SCANCODE_LGUI || key == SDL_SCANCODE_RGUI)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!mDetectingKeyboard)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clearAllKeyBindings(mInputBinder, control);
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
ICS::DetectingBindingListener::keyBindingDetected(ICS, control, key, direction);
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
||||||
|
, ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
// we don't want mouse movement bindings
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
||||||
|
, unsigned int button, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
if (!mDetectingKeyboard)
|
||||||
|
return;
|
||||||
|
clearAllKeyBindings(mInputBinder, control);
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
ICS::DetectingBindingListener::mouseButtonBindingDetected(ICS, control, button, direction);
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
||||||
|
, ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
if (!mDetectingKeyboard)
|
||||||
|
return;
|
||||||
|
clearAllKeyBindings(mInputBinder, control);
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
ICS::DetectingBindingListener::mouseWheelBindingDetected(ICS, control, click, direction);
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control
|
||||||
|
, int axis, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
//only allow binding to the trigers
|
||||||
|
if (axis != SDL_CONTROLLER_AXIS_TRIGGERLEFT && axis != SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||||
|
return;
|
||||||
|
if (mDetectingKeyboard)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clearAllControllerBindings(mInputBinder, control);
|
||||||
|
control->setValue(0.5f); //axis bindings must start at 0.5
|
||||||
|
control->setInitialValue(0.5f);
|
||||||
|
ICS::DetectingBindingListener::joystickAxisBindingDetected(ICS, deviceID, control, axis, direction);
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control
|
||||||
|
, unsigned int button, ICS::Control::ControlChangingDirection direction)
|
||||||
|
{
|
||||||
|
if (mDetectingKeyboard)
|
||||||
|
return;
|
||||||
|
clearAllControllerBindings(mInputBinder,control);
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, deviceID, control, button, direction);
|
||||||
|
MWBase::Environment::get().getWindowManager()->notifyInputActionBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDetectingKeyboard(bool detecting)
|
||||||
|
{
|
||||||
|
mDetectingKeyboard = detecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ICS::InputControlSystem* mInputBinder;
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
|
bool mDetectingKeyboard;
|
||||||
|
};
|
||||||
|
|
||||||
|
BindingsManager::BindingsManager(const std::string& userFile, bool userFileExists)
|
||||||
|
: mUserFile(userFile)
|
||||||
|
, mDragDrop(false)
|
||||||
|
{
|
||||||
|
std::string file = userFileExists ? userFile : "";
|
||||||
|
mInputBinder = new InputControlSystem(file);
|
||||||
|
mListener = new BindingsListener(mInputBinder, this);
|
||||||
|
mInputBinder->setDetectingBindingListener(mListener);
|
||||||
|
|
||||||
|
loadKeyDefaults();
|
||||||
|
loadControllerDefaults();
|
||||||
|
|
||||||
|
for (int i = 0; i < A_Last; ++i)
|
||||||
|
{
|
||||||
|
mInputBinder->getChannel(i)->addListener(mListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::setDragDrop(bool dragDrop)
|
||||||
|
{
|
||||||
|
mDragDrop = dragDrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingsManager::~BindingsManager()
|
||||||
|
{
|
||||||
|
mInputBinder->save(mUserFile);
|
||||||
|
delete mInputBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::update(float dt)
|
||||||
|
{
|
||||||
|
// update values of channels (as a result of pressed keys)
|
||||||
|
mInputBinder->update(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BindingsManager::isLeftOrRightButton(int action, bool joystick) const
|
||||||
|
{
|
||||||
|
int mouseBinding = mInputBinder->getMouseButtonBinding(mInputBinder->getControl(action), ICS::Control::INCREASE);
|
||||||
|
if (mouseBinding != ICS_MAX_DEVICE_BUTTONS)
|
||||||
|
return true;
|
||||||
|
int buttonBinding = mInputBinder->getJoystickButtonBinding(mInputBinder->getControl(action), sFakeDeviceId, ICS::Control::INCREASE);
|
||||||
|
if (joystick && (buttonBinding == 0 || buttonBinding == 1))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::setPlayerControlsEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
int playerChannels[] = {A_AutoMove, A_AlwaysRun, A_ToggleWeapon,
|
||||||
|
A_ToggleSpell, A_Rest, A_QuickKey1, A_QuickKey2,
|
||||||
|
A_QuickKey3, A_QuickKey4, A_QuickKey5, A_QuickKey6,
|
||||||
|
A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10,
|
||||||
|
A_Use, A_Journal};
|
||||||
|
|
||||||
|
for(int pc : playerChannels)
|
||||||
|
{
|
||||||
|
mInputBinder->getChannel(pc)->setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float BindingsManager::getActionValue (int id) const
|
||||||
|
{
|
||||||
|
return mInputBinder->getChannel(id)->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BindingsManager::actionIsActive (int id) const
|
||||||
|
{
|
||||||
|
return getActionValue(id) == 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::loadKeyDefaults (bool force)
|
||||||
|
{
|
||||||
|
// using hardcoded key defaults is inevitable, if we want the configuration files to stay valid
|
||||||
|
// across different versions of OpenMW (in the case where another input action is added)
|
||||||
|
std::map<int, SDL_Scancode> defaultKeyBindings;
|
||||||
|
|
||||||
|
//Gets the Keyvalue from the Scancode; gives the button in the same place reguardless of keyboard format
|
||||||
|
defaultKeyBindings[A_Activate] = SDL_SCANCODE_SPACE;
|
||||||
|
defaultKeyBindings[A_MoveBackward] = SDL_SCANCODE_S;
|
||||||
|
defaultKeyBindings[A_MoveForward] = SDL_SCANCODE_W;
|
||||||
|
defaultKeyBindings[A_MoveLeft] = SDL_SCANCODE_A;
|
||||||
|
defaultKeyBindings[A_MoveRight] = SDL_SCANCODE_D;
|
||||||
|
defaultKeyBindings[A_ToggleWeapon] = SDL_SCANCODE_F;
|
||||||
|
defaultKeyBindings[A_ToggleSpell] = SDL_SCANCODE_R;
|
||||||
|
defaultKeyBindings[A_CycleSpellLeft] = SDL_SCANCODE_MINUS;
|
||||||
|
defaultKeyBindings[A_CycleSpellRight] = SDL_SCANCODE_EQUALS;
|
||||||
|
defaultKeyBindings[A_CycleWeaponLeft] = SDL_SCANCODE_LEFTBRACKET;
|
||||||
|
defaultKeyBindings[A_CycleWeaponRight] = SDL_SCANCODE_RIGHTBRACKET;
|
||||||
|
|
||||||
|
defaultKeyBindings[A_QuickKeysMenu] = SDL_SCANCODE_F1;
|
||||||
|
defaultKeyBindings[A_Console] = SDL_SCANCODE_GRAVE;
|
||||||
|
defaultKeyBindings[A_Run] = SDL_SCANCODE_LSHIFT;
|
||||||
|
defaultKeyBindings[A_Sneak] = SDL_SCANCODE_LCTRL;
|
||||||
|
defaultKeyBindings[A_AutoMove] = SDL_SCANCODE_Q;
|
||||||
|
defaultKeyBindings[A_Jump] = SDL_SCANCODE_E;
|
||||||
|
defaultKeyBindings[A_Journal] = SDL_SCANCODE_J;
|
||||||
|
defaultKeyBindings[A_Rest] = SDL_SCANCODE_T;
|
||||||
|
defaultKeyBindings[A_GameMenu] = SDL_SCANCODE_ESCAPE;
|
||||||
|
defaultKeyBindings[A_TogglePOV] = SDL_SCANCODE_TAB;
|
||||||
|
defaultKeyBindings[A_QuickKey1] = SDL_SCANCODE_1;
|
||||||
|
defaultKeyBindings[A_QuickKey2] = SDL_SCANCODE_2;
|
||||||
|
defaultKeyBindings[A_QuickKey3] = SDL_SCANCODE_3;
|
||||||
|
defaultKeyBindings[A_QuickKey4] = SDL_SCANCODE_4;
|
||||||
|
defaultKeyBindings[A_QuickKey5] = SDL_SCANCODE_5;
|
||||||
|
defaultKeyBindings[A_QuickKey6] = SDL_SCANCODE_6;
|
||||||
|
defaultKeyBindings[A_QuickKey7] = SDL_SCANCODE_7;
|
||||||
|
defaultKeyBindings[A_QuickKey8] = SDL_SCANCODE_8;
|
||||||
|
defaultKeyBindings[A_QuickKey9] = SDL_SCANCODE_9;
|
||||||
|
defaultKeyBindings[A_QuickKey10] = SDL_SCANCODE_0;
|
||||||
|
defaultKeyBindings[A_Screenshot] = SDL_SCANCODE_F12;
|
||||||
|
defaultKeyBindings[A_ToggleHUD] = SDL_SCANCODE_F11;
|
||||||
|
defaultKeyBindings[A_ToggleDebug] = SDL_SCANCODE_F10;
|
||||||
|
defaultKeyBindings[A_AlwaysRun] = SDL_SCANCODE_CAPSLOCK;
|
||||||
|
defaultKeyBindings[A_QuickSave] = SDL_SCANCODE_F5;
|
||||||
|
defaultKeyBindings[A_QuickLoad] = SDL_SCANCODE_F9;
|
||||||
|
|
||||||
|
std::map<int, int> defaultMouseButtonBindings;
|
||||||
|
defaultMouseButtonBindings[A_Inventory] = SDL_BUTTON_RIGHT;
|
||||||
|
defaultMouseButtonBindings[A_Use] = SDL_BUTTON_LEFT;
|
||||||
|
|
||||||
|
std::map<int, ICS::InputControlSystem::MouseWheelClick> defaultMouseWheelBindings;
|
||||||
|
defaultMouseWheelBindings[A_ZoomIn] = ICS::InputControlSystem::MouseWheelClick::UP;
|
||||||
|
defaultMouseWheelBindings[A_ZoomOut] = ICS::InputControlSystem::MouseWheelClick::DOWN;
|
||||||
|
|
||||||
|
for (int i = 0; i < A_Last; ++i)
|
||||||
|
{
|
||||||
|
ICS::Control* control;
|
||||||
|
bool controlExists = mInputBinder->getChannel(i)->getControlsCount() != 0;
|
||||||
|
if (!controlExists)
|
||||||
|
{
|
||||||
|
control = new ICS::Control(std::to_string(i), false, true, 0, ICS::ICS_MAX, ICS::ICS_MAX);
|
||||||
|
mInputBinder->addControl(control);
|
||||||
|
control->attachChannel(mInputBinder->getChannel(i), ICS::Channel::DIRECT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
control = mInputBinder->getChannel(i)->getAttachedControls().front().control;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!controlExists || force ||
|
||||||
|
(mInputBinder->getKeyBinding(control, ICS::Control::INCREASE) == SDL_SCANCODE_UNKNOWN
|
||||||
|
&& mInputBinder->getMouseButtonBinding(control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS
|
||||||
|
&& mInputBinder->getMouseWheelBinding(control, ICS::Control::INCREASE) == ICS::InputControlSystem::MouseWheelClick::UNASSIGNED))
|
||||||
|
{
|
||||||
|
clearAllKeyBindings(mInputBinder, control);
|
||||||
|
|
||||||
|
if (defaultKeyBindings.find(i) != defaultKeyBindings.end()
|
||||||
|
&& (force || !mInputBinder->isKeyBound(defaultKeyBindings[i])))
|
||||||
|
{
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()
|
||||||
|
&& (force || !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i])))
|
||||||
|
{
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
mInputBinder->addMouseButtonBinding(control, defaultMouseButtonBindings[i], ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
else if (defaultMouseWheelBindings.find(i) != defaultMouseWheelBindings.end()
|
||||||
|
&& (force || !mInputBinder->isMouseWheelBound(defaultMouseWheelBindings[i])))
|
||||||
|
{
|
||||||
|
control->setInitialValue(0.f);
|
||||||
|
mInputBinder->addMouseWheelBinding(control, defaultMouseWheelBindings[i], ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == A_LookLeftRight && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_4) && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_6))
|
||||||
|
{
|
||||||
|
mInputBinder->addKeyBinding(control, SDL_SCANCODE_KP_6, ICS::Control::INCREASE);
|
||||||
|
mInputBinder->addKeyBinding(control, SDL_SCANCODE_KP_4, ICS::Control::DECREASE);
|
||||||
|
}
|
||||||
|
if (i == A_LookUpDown && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_8) && !mInputBinder->isKeyBound(SDL_SCANCODE_KP_2))
|
||||||
|
{
|
||||||
|
mInputBinder->addKeyBinding(control, SDL_SCANCODE_KP_2, ICS::Control::INCREASE);
|
||||||
|
mInputBinder->addKeyBinding(control, SDL_SCANCODE_KP_8, ICS::Control::DECREASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::loadControllerDefaults(bool force)
|
||||||
|
{
|
||||||
|
// using hardcoded key defaults is inevitable, if we want the configuration files to stay valid
|
||||||
|
// across different versions of OpenMW (in the case where another input action is added)
|
||||||
|
std::map<int, int> defaultButtonBindings;
|
||||||
|
|
||||||
|
defaultButtonBindings[A_Activate] = SDL_CONTROLLER_BUTTON_A;
|
||||||
|
defaultButtonBindings[A_ToggleWeapon] = SDL_CONTROLLER_BUTTON_X;
|
||||||
|
defaultButtonBindings[A_ToggleSpell] = SDL_CONTROLLER_BUTTON_Y;
|
||||||
|
//defaultButtonBindings[A_QuickButtonsMenu] = SDL_GetButtonFromScancode(SDL_SCANCODE_F1); // Need to implement, should be ToggleSpell(5) AND Wait(9)
|
||||||
|
defaultButtonBindings[A_Sneak] = SDL_CONTROLLER_BUTTON_LEFTSTICK;
|
||||||
|
defaultButtonBindings[A_Journal] = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
|
||||||
|
defaultButtonBindings[A_Rest] = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
|
||||||
|
defaultButtonBindings[A_TogglePOV] = SDL_CONTROLLER_BUTTON_RIGHTSTICK;
|
||||||
|
defaultButtonBindings[A_Inventory] = SDL_CONTROLLER_BUTTON_B;
|
||||||
|
defaultButtonBindings[A_GameMenu] = SDL_CONTROLLER_BUTTON_START;
|
||||||
|
defaultButtonBindings[A_QuickSave] = SDL_CONTROLLER_BUTTON_GUIDE;
|
||||||
|
defaultButtonBindings[A_MoveForward] = SDL_CONTROLLER_BUTTON_DPAD_UP;
|
||||||
|
defaultButtonBindings[A_MoveLeft] = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
|
||||||
|
defaultButtonBindings[A_MoveBackward] = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
|
||||||
|
defaultButtonBindings[A_MoveRight] = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
|
||||||
|
|
||||||
|
std::map<int, int> defaultAxisBindings;
|
||||||
|
defaultAxisBindings[A_MoveForwardBackward] = SDL_CONTROLLER_AXIS_LEFTY;
|
||||||
|
defaultAxisBindings[A_MoveLeftRight] = SDL_CONTROLLER_AXIS_LEFTX;
|
||||||
|
defaultAxisBindings[A_LookUpDown] = SDL_CONTROLLER_AXIS_RIGHTY;
|
||||||
|
defaultAxisBindings[A_LookLeftRight] = SDL_CONTROLLER_AXIS_RIGHTX;
|
||||||
|
defaultAxisBindings[A_Use] = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
|
||||||
|
defaultAxisBindings[A_Jump] = SDL_CONTROLLER_AXIS_TRIGGERLEFT;
|
||||||
|
|
||||||
|
for (int i = 0; i < A_Last; i++)
|
||||||
|
{
|
||||||
|
ICS::Control* control;
|
||||||
|
bool controlExists = mInputBinder->getChannel(i)->getControlsCount() != 0;
|
||||||
|
if (!controlExists)
|
||||||
|
{
|
||||||
|
float initial;
|
||||||
|
if (defaultAxisBindings.find(i) == defaultAxisBindings.end())
|
||||||
|
initial = 0.0f;
|
||||||
|
else initial = 0.5f;
|
||||||
|
control = new ICS::Control(std::to_string(i), false, true, initial, ICS::ICS_MAX, ICS::ICS_MAX);
|
||||||
|
mInputBinder->addControl(control);
|
||||||
|
control->attachChannel(mInputBinder->getChannel(i), ICS::Channel::DIRECT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
control = mInputBinder->getChannel(i)->getAttachedControls().front().control;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!controlExists || force || (mInputBinder->getJoystickAxisBinding(control, sFakeDeviceId, ICS::Control::INCREASE) == ICS::InputControlSystem::UNASSIGNED &&
|
||||||
|
mInputBinder->getJoystickButtonBinding(control, sFakeDeviceId, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS))
|
||||||
|
{
|
||||||
|
clearAllControllerBindings(mInputBinder, control);
|
||||||
|
|
||||||
|
if (defaultButtonBindings.find(i) != defaultButtonBindings.end()
|
||||||
|
&& (force || !mInputBinder->isJoystickButtonBound(sFakeDeviceId, defaultButtonBindings[i])))
|
||||||
|
{
|
||||||
|
control->setInitialValue(0.0f);
|
||||||
|
mInputBinder->addJoystickButtonBinding(control, sFakeDeviceId, defaultButtonBindings[i], ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
else if (defaultAxisBindings.find(i) != defaultAxisBindings.end() && (force || !mInputBinder->isJoystickAxisBound(sFakeDeviceId, defaultAxisBindings[i])))
|
||||||
|
{
|
||||||
|
control->setValue(0.5f);
|
||||||
|
control->setInitialValue(0.5f);
|
||||||
|
mInputBinder->addJoystickAxisBinding(control, sFakeDeviceId, defaultAxisBindings[i], ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BindingsManager::getActionDescription(int action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case A_Screenshot:
|
||||||
|
return "Screenshot";
|
||||||
|
case A_ZoomIn:
|
||||||
|
return "Zoom In";
|
||||||
|
case A_ZoomOut:
|
||||||
|
return "Zoom Out";
|
||||||
|
case A_ToggleHUD:
|
||||||
|
return "Toggle HUD";
|
||||||
|
case A_Use:
|
||||||
|
return "#{sUse}";
|
||||||
|
case A_Activate:
|
||||||
|
return "#{sActivate}";
|
||||||
|
case A_MoveBackward:
|
||||||
|
return "#{sBack}";
|
||||||
|
case A_MoveForward:
|
||||||
|
return "#{sForward}";
|
||||||
|
case A_MoveLeft:
|
||||||
|
return "#{sLeft}";
|
||||||
|
case A_MoveRight:
|
||||||
|
return "#{sRight}";
|
||||||
|
case A_ToggleWeapon:
|
||||||
|
return "#{sReady_Weapon}";
|
||||||
|
case A_ToggleSpell:
|
||||||
|
return "#{sReady_Magic}";
|
||||||
|
case A_CycleSpellLeft:
|
||||||
|
return "#{sPrevSpell}";
|
||||||
|
case A_CycleSpellRight:
|
||||||
|
return "#{sNextSpell}";
|
||||||
|
case A_CycleWeaponLeft:
|
||||||
|
return "#{sPrevWeapon}";
|
||||||
|
case A_CycleWeaponRight:
|
||||||
|
return "#{sNextWeapon}";
|
||||||
|
case A_Console:
|
||||||
|
return "#{sConsoleTitle}";
|
||||||
|
case A_Run:
|
||||||
|
return "#{sRun}";
|
||||||
|
case A_Sneak:
|
||||||
|
return "#{sCrouch_Sneak}";
|
||||||
|
case A_AutoMove:
|
||||||
|
return "#{sAuto_Run}";
|
||||||
|
case A_Jump:
|
||||||
|
return "#{sJump}";
|
||||||
|
case A_Journal:
|
||||||
|
return "#{sJournal}";
|
||||||
|
case A_Rest:
|
||||||
|
return "#{sRestKey}";
|
||||||
|
case A_Inventory:
|
||||||
|
return "#{sInventory}";
|
||||||
|
case A_TogglePOV:
|
||||||
|
return "#{sTogglePOVCmd}";
|
||||||
|
case A_QuickKeysMenu:
|
||||||
|
return "#{sQuickMenu}";
|
||||||
|
case A_QuickKey1:
|
||||||
|
return "#{sQuick1Cmd}";
|
||||||
|
case A_QuickKey2:
|
||||||
|
return "#{sQuick2Cmd}";
|
||||||
|
case A_QuickKey3:
|
||||||
|
return "#{sQuick3Cmd}";
|
||||||
|
case A_QuickKey4:
|
||||||
|
return "#{sQuick4Cmd}";
|
||||||
|
case A_QuickKey5:
|
||||||
|
return "#{sQuick5Cmd}";
|
||||||
|
case A_QuickKey6:
|
||||||
|
return "#{sQuick6Cmd}";
|
||||||
|
case A_QuickKey7:
|
||||||
|
return "#{sQuick7Cmd}";
|
||||||
|
case A_QuickKey8:
|
||||||
|
return "#{sQuick8Cmd}";
|
||||||
|
case A_QuickKey9:
|
||||||
|
return "#{sQuick9Cmd}";
|
||||||
|
case A_QuickKey10:
|
||||||
|
return "#{sQuick10Cmd}";
|
||||||
|
case A_AlwaysRun:
|
||||||
|
return "#{sAlways_Run}";
|
||||||
|
case A_QuickSave:
|
||||||
|
return "#{sQuickSaveCmd}";
|
||||||
|
case A_QuickLoad:
|
||||||
|
return "#{sQuickLoadCmd}";
|
||||||
|
default:
|
||||||
|
return std::string(); // not configurable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BindingsManager::getActionKeyBindingName(int action)
|
||||||
|
{
|
||||||
|
if (mInputBinder->getChannel(action)->getControlsCount() == 0)
|
||||||
|
return "#{sNone}";
|
||||||
|
|
||||||
|
ICS::Control* c = mInputBinder->getChannel(action)->getAttachedControls().front().control;
|
||||||
|
|
||||||
|
SDL_Scancode key = mInputBinder->getKeyBinding(c, ICS::Control::INCREASE);
|
||||||
|
unsigned int mouse = mInputBinder->getMouseButtonBinding(c, ICS::Control::INCREASE);
|
||||||
|
ICS::InputControlSystem::MouseWheelClick wheel = mInputBinder->getMouseWheelBinding(c, ICS::Control::INCREASE);
|
||||||
|
if (key != SDL_SCANCODE_UNKNOWN)
|
||||||
|
return MyGUI::TextIterator::toTagsString(mInputBinder->scancodeToString(key));
|
||||||
|
else if (mouse != ICS_MAX_DEVICE_BUTTONS)
|
||||||
|
return "#{sMouse} " + std::to_string(mouse);
|
||||||
|
else if (wheel != ICS::InputControlSystem::MouseWheelClick::UNASSIGNED)
|
||||||
|
switch (wheel)
|
||||||
|
{
|
||||||
|
case ICS::InputControlSystem::MouseWheelClick::UP:
|
||||||
|
return "Mouse Wheel Up";
|
||||||
|
case ICS::InputControlSystem::MouseWheelClick::DOWN:
|
||||||
|
return "Mouse Wheel Down";
|
||||||
|
case ICS::InputControlSystem::MouseWheelClick::RIGHT:
|
||||||
|
return "Mouse Wheel Right";
|
||||||
|
case ICS::InputControlSystem::MouseWheelClick::LEFT:
|
||||||
|
return "Mouse Wheel Left";
|
||||||
|
default:
|
||||||
|
return "#{sNone}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "#{sNone}";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BindingsManager::getActionControllerBindingName(int action)
|
||||||
|
{
|
||||||
|
if (mInputBinder->getChannel(action)->getControlsCount() == 0)
|
||||||
|
return "#{sNone}";
|
||||||
|
|
||||||
|
ICS::Control* c = mInputBinder->getChannel(action)->getAttachedControls().front().control;
|
||||||
|
|
||||||
|
if (mInputBinder->getJoystickAxisBinding(c, sFakeDeviceId, ICS::Control::INCREASE) != ICS::InputControlSystem::UNASSIGNED)
|
||||||
|
return sdlControllerAxisToString(mInputBinder->getJoystickAxisBinding(c, sFakeDeviceId, ICS::Control::INCREASE));
|
||||||
|
else if (mInputBinder->getJoystickButtonBinding(c, sFakeDeviceId, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS)
|
||||||
|
return sdlControllerButtonToString(mInputBinder->getJoystickButtonBinding(c, sFakeDeviceId, ICS::Control::INCREASE));
|
||||||
|
else
|
||||||
|
return "#{sNone}";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> BindingsManager::getActionKeySorting()
|
||||||
|
{
|
||||||
|
static const std::vector<int> actions
|
||||||
|
{
|
||||||
|
A_MoveForward, A_MoveBackward, A_MoveLeft, A_MoveRight, A_TogglePOV, A_ZoomIn, A_ZoomOut,
|
||||||
|
A_Run, A_AlwaysRun, A_Sneak, A_Activate, A_Use, A_ToggleWeapon, A_ToggleSpell,
|
||||||
|
A_CycleSpellLeft, A_CycleSpellRight, A_CycleWeaponLeft, A_CycleWeaponRight, A_AutoMove,
|
||||||
|
A_Jump, A_Inventory, A_Journal, A_Rest, A_Console, A_QuickSave, A_QuickLoad,
|
||||||
|
A_ToggleHUD, A_Screenshot, A_QuickKeysMenu, A_QuickKey1, A_QuickKey2, A_QuickKey3,
|
||||||
|
A_QuickKey4, A_QuickKey5, A_QuickKey6, A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10
|
||||||
|
};
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
std::vector<int> BindingsManager::getActionControllerSorting()
|
||||||
|
{
|
||||||
|
static const std::vector<int> actions
|
||||||
|
{
|
||||||
|
A_TogglePOV, A_ZoomIn, A_ZoomOut, A_Sneak, A_Activate, A_Use, A_ToggleWeapon, A_ToggleSpell,
|
||||||
|
A_AutoMove, A_Jump, A_Inventory, A_Journal, A_Rest, A_QuickSave, A_QuickLoad, A_ToggleHUD,
|
||||||
|
A_Screenshot, A_QuickKeysMenu, A_QuickKey1, A_QuickKey2, A_QuickKey3, A_QuickKey4,
|
||||||
|
A_QuickKey5, A_QuickKey6, A_QuickKey7, A_QuickKey8, A_QuickKey9, A_QuickKey10,
|
||||||
|
A_CycleSpellLeft, A_CycleSpellRight, A_CycleWeaponLeft, A_CycleWeaponRight
|
||||||
|
};
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::enableDetectingBindingMode(int action, bool keyboard)
|
||||||
|
{
|
||||||
|
mListener->setDetectingKeyboard(keyboard);
|
||||||
|
ICS::Control* c = mInputBinder->getChannel(action)->getAttachedControls().front().control;
|
||||||
|
mInputBinder->enableDetectingBindingState(c, ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BindingsManager::isDetectingBindingState() const
|
||||||
|
{
|
||||||
|
return mInputBinder->detectingBindingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::mousePressed(const SDL_MouseButtonEvent &arg, int deviceID)
|
||||||
|
{
|
||||||
|
mInputBinder->mousePressed(arg, deviceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::mouseReleased(const SDL_MouseButtonEvent &arg, int deviceID)
|
||||||
|
{
|
||||||
|
mInputBinder->mouseReleased(arg, deviceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::mouseMoved(const SDLUtil::MouseMotionEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->mouseMoved(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::mouseWheelMoved(const SDL_MouseWheelEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->mouseWheelMoved(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::keyPressed(const SDL_KeyboardEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->keyPressed(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::keyReleased(const SDL_KeyboardEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->keyReleased(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->controllerAdded(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->controllerRemoved(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::controllerButtonPressed(int deviceID, const SDL_ControllerButtonEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->buttonPressed(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::controllerButtonReleased(int deviceID, const SDL_ControllerButtonEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->buttonReleased(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::controllerAxisMoved(int deviceID, const SDL_ControllerAxisEvent &arg)
|
||||||
|
{
|
||||||
|
mInputBinder->axisMoved(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Scancode BindingsManager::getKeyBinding(int actionId)
|
||||||
|
{
|
||||||
|
return mInputBinder->getKeyBinding(mInputBinder->getControl(actionId), ICS::Control::INCREASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindingsManager::actionValueChanged(int action, float currentValue, float previousValue)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
|
||||||
|
if (mDragDrop && action != A_GameMenu && action != A_Inventory)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((previousValue == 1 || previousValue == 0) && (currentValue==1 || currentValue==0))
|
||||||
|
{
|
||||||
|
//Is a normal button press, so don't change it at all
|
||||||
|
}
|
||||||
|
//Otherwise only trigger button presses as they go through specific points
|
||||||
|
else if (previousValue >= 0.8 && currentValue < 0.8)
|
||||||
|
{
|
||||||
|
currentValue = 0.0;
|
||||||
|
previousValue = 1.0;
|
||||||
|
}
|
||||||
|
else if (previousValue <= 0.6 && currentValue > 0.6)
|
||||||
|
{
|
||||||
|
currentValue = 1.0;
|
||||||
|
previousValue = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//If it's not switching between those values, ignore the channel change.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
bool joystickUsed = MWBase::Environment::get().getInputManager()->joystickLastUsed();
|
||||||
|
if (action == A_Use)
|
||||||
|
{
|
||||||
|
if (joystickUsed && currentValue == 1.0 && actionIsActive(A_ToggleWeapon))
|
||||||
|
action = A_CycleWeaponRight;
|
||||||
|
|
||||||
|
else if (joystickUsed && currentValue == 1.0 && actionIsActive(A_ToggleSpell))
|
||||||
|
action = A_CycleSpellRight;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
MWMechanics::DrawState_ state = player.getDrawState();
|
||||||
|
player.setAttackingOrSpell(currentValue != 0 && state != MWMechanics::DrawState_Nothing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == A_Jump)
|
||||||
|
{
|
||||||
|
if (joystickUsed && currentValue == 1.0 && actionIsActive(A_ToggleWeapon))
|
||||||
|
action = A_CycleWeaponLeft;
|
||||||
|
|
||||||
|
else if (joystickUsed && currentValue == 1.0 && actionIsActive(A_ToggleSpell))
|
||||||
|
action = A_CycleSpellLeft;
|
||||||
|
|
||||||
|
else
|
||||||
|
MWBase::Environment::get().getInputManager()->setAttemptJump(currentValue == 1.0 && previousValue == 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue == 1)
|
||||||
|
MWBase::Environment::get().getInputManager()->executeAction(action);
|
||||||
|
}
|
||||||
|
}
|
73
apps/openmw/mwinput/bindingsmanager.hpp
Normal file
73
apps/openmw/mwinput/bindingsmanager.hpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef MWINPUT_MWBINDINGSMANAGER_H
|
||||||
|
#define MWINPUT_MWBINDINGSMANAGER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class BindingsListener;
|
||||||
|
class InputControlSystem;
|
||||||
|
|
||||||
|
class BindingsManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BindingsManager(const std::string& userFile, bool userFileExists);
|
||||||
|
|
||||||
|
virtual ~BindingsManager();
|
||||||
|
|
||||||
|
std::string getActionDescription (int action);
|
||||||
|
std::string getActionKeyBindingName (int action);
|
||||||
|
std::string getActionControllerBindingName (int action);
|
||||||
|
std::vector<int> getActionKeySorting();
|
||||||
|
std::vector<int> getActionControllerSorting();
|
||||||
|
|
||||||
|
void enableDetectingBindingMode (int action, bool keyboard);
|
||||||
|
bool isDetectingBindingState() const;
|
||||||
|
|
||||||
|
void loadKeyDefaults(bool force = false);
|
||||||
|
void loadControllerDefaults(bool force = false);
|
||||||
|
|
||||||
|
void setDragDrop(bool dragDrop);
|
||||||
|
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
|
void setPlayerControlsEnabled(bool enabled);
|
||||||
|
|
||||||
|
bool isLeftOrRightButton(int action, bool joystick) const;
|
||||||
|
|
||||||
|
bool actionIsActive(int id) const;
|
||||||
|
float getActionValue(int id) const;
|
||||||
|
|
||||||
|
void mousePressed(const SDL_MouseButtonEvent &evt, int deviceID);
|
||||||
|
void mouseReleased(const SDL_MouseButtonEvent &arg, int deviceID);
|
||||||
|
void mouseMoved(const SDLUtil::MouseMotionEvent &arg);
|
||||||
|
void mouseWheelMoved(const SDL_MouseWheelEvent &arg);
|
||||||
|
|
||||||
|
void keyPressed(const SDL_KeyboardEvent &arg);
|
||||||
|
void keyReleased(const SDL_KeyboardEvent &arg);
|
||||||
|
|
||||||
|
void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg);
|
||||||
|
void controllerRemoved(const SDL_ControllerDeviceEvent &arg);
|
||||||
|
void controllerButtonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
|
void controllerButtonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
|
void controllerAxisMoved(int deviceID, const SDL_ControllerAxisEvent &arg);
|
||||||
|
|
||||||
|
SDL_Scancode getKeyBinding(int actionId);
|
||||||
|
|
||||||
|
void actionValueChanged(int action, float currentValue, float previousValue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupSDLKeyMappings();
|
||||||
|
|
||||||
|
InputControlSystem* mInputBinder;
|
||||||
|
BindingsListener* mListener;
|
||||||
|
|
||||||
|
std::string mUserFile;
|
||||||
|
|
||||||
|
bool mDragDrop;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
398
apps/openmw/mwinput/controllermanager.cpp
Normal file
398
apps/openmw/mwinput/controllermanager.cpp
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
#include "controllermanager.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
#include "actionmanager.hpp"
|
||||||
|
#include "bindingsmanager.hpp"
|
||||||
|
#include "mousemanager.hpp"
|
||||||
|
#include "sdlmappings.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
ControllerManager::ControllerManager(BindingsManager* bindingsManager,
|
||||||
|
ActionManager* actionManager,
|
||||||
|
MouseManager* mouseManager,
|
||||||
|
const std::string& userControllerBindingsFile,
|
||||||
|
const std::string& controllerBindingsFile)
|
||||||
|
: mBindingsManager(bindingsManager)
|
||||||
|
, mActionManager(actionManager)
|
||||||
|
, mMouseManager(mouseManager)
|
||||||
|
, mJoystickEnabled (Settings::Manager::getBool("enable controller", "Input"))
|
||||||
|
, mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input"))
|
||||||
|
, mInvUiScalingFactor(1.f)
|
||||||
|
, mSneakToggleShortcutTimer(0.f)
|
||||||
|
, mGamepadZoom(0)
|
||||||
|
, mGamepadGuiCursorEnabled(true)
|
||||||
|
, mJoystickLastUsed(false)
|
||||||
|
, mSneakGamepadShortcut(false)
|
||||||
|
, mGamepadPreviewMode(false)
|
||||||
|
{
|
||||||
|
if (!controllerBindingsFile.empty())
|
||||||
|
{
|
||||||
|
SDL_GameControllerAddMappingsFromFile(controllerBindingsFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userControllerBindingsFile.empty())
|
||||||
|
{
|
||||||
|
SDL_GameControllerAddMappingsFromFile(userControllerBindingsFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open all presently connected sticks
|
||||||
|
int numSticks = SDL_NumJoysticks();
|
||||||
|
for (int i = 0; i < numSticks; i++)
|
||||||
|
{
|
||||||
|
if (SDL_IsGameController(i))
|
||||||
|
{
|
||||||
|
SDL_ControllerDeviceEvent evt;
|
||||||
|
evt.which = i;
|
||||||
|
static const int fakeDeviceID = 1;
|
||||||
|
controllerAdded(fakeDeviceID, evt);
|
||||||
|
Log(Debug::Info) << "Detected game controller: " << SDL_GameControllerNameForIndex(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log(Debug::Info) << "Detected unusable controller: " << SDL_JoystickNameForIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
|
if (uiScale != 0.f)
|
||||||
|
mInvUiScalingFactor = 1.f / uiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
|
{
|
||||||
|
for (const auto& setting : changed)
|
||||||
|
{
|
||||||
|
if (setting.first == "Input" && setting.second == "enable controller")
|
||||||
|
mJoystickEnabled = Settings::Manager::getBool("enable controller", "Input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerManager::update(float dt)
|
||||||
|
{
|
||||||
|
mGamepadPreviewMode = mActionManager->getPreviewDelay() == 1.f;
|
||||||
|
|
||||||
|
if (mGuiCursorEnabled && !(mJoystickLastUsed && !mGamepadGuiCursorEnabled))
|
||||||
|
{
|
||||||
|
float xAxis = mBindingsManager->getActionValue(A_MoveLeftRight) * 2.0f - 1.0f;
|
||||||
|
float yAxis = mBindingsManager->getActionValue(A_MoveForwardBackward) * 2.0f - 1.0f;
|
||||||
|
float zAxis = mBindingsManager->getActionValue(A_LookUpDown) * 2.0f - 1.0f;
|
||||||
|
|
||||||
|
xAxis *= (1.5f - mBindingsManager->getActionValue(A_Use));
|
||||||
|
yAxis *= (1.5f - mBindingsManager->getActionValue(A_Use));
|
||||||
|
|
||||||
|
// We keep track of our own mouse position, so that moving the mouse while in
|
||||||
|
// game mode does not move the position of the GUI cursor
|
||||||
|
float xMove = xAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed;
|
||||||
|
float yMove = yAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed;
|
||||||
|
if (xMove != 0 || yMove != 0 || zAxis != 0)
|
||||||
|
{
|
||||||
|
int mouseWheelMove = static_cast<int>(-zAxis * dt * 1500.0f);
|
||||||
|
|
||||||
|
mMouseManager->injectMouseMove(xMove, yMove, mouseWheelMove);
|
||||||
|
mMouseManager->warpMouse();
|
||||||
|
MWBase::Environment::get().getWindowManager()->setCursorActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable movement in Gui mode
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()
|
||||||
|
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)
|
||||||
|
{
|
||||||
|
mGamepadZoom = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
bool triedToMove = false;
|
||||||
|
|
||||||
|
// Configure player movement according to controller input. Actual movement will
|
||||||
|
// be done in the physics system.
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
float xAxis = mBindingsManager->getActionValue(A_MoveLeftRight);
|
||||||
|
float yAxis = mBindingsManager->getActionValue(A_MoveForwardBackward);
|
||||||
|
if (xAxis != 0.5)
|
||||||
|
{
|
||||||
|
triedToMove = true;
|
||||||
|
player.setLeftRight((xAxis - 0.5f) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yAxis != 0.5)
|
||||||
|
{
|
||||||
|
triedToMove = true;
|
||||||
|
player.setAutoMove (false);
|
||||||
|
player.setForwardBackward((0.5f - yAxis) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triedToMove)
|
||||||
|
{
|
||||||
|
mJoystickLastUsed = true;
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const bool isToggleSneak = Settings::Manager::getBool("toggle sneak", "Input");
|
||||||
|
if (!isToggleSneak)
|
||||||
|
{
|
||||||
|
if (mJoystickLastUsed)
|
||||||
|
{
|
||||||
|
if (mBindingsManager->actionIsActive(A_Sneak))
|
||||||
|
{
|
||||||
|
if (mSneakToggleShortcutTimer) // New Sneak Button Press
|
||||||
|
{
|
||||||
|
if (mSneakToggleShortcutTimer <= 0.3f)
|
||||||
|
{
|
||||||
|
mSneakGamepadShortcut = true;
|
||||||
|
mActionManager->toggleSneaking();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mSneakGamepadShortcut = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mActionManager->isSneaking())
|
||||||
|
mActionManager->toggleSneaking();
|
||||||
|
mSneakToggleShortcutTimer = 0.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!mSneakGamepadShortcut && mActionManager->isSneaking())
|
||||||
|
mActionManager->toggleSneaking();
|
||||||
|
if (mSneakToggleShortcutTimer <= 0.3f)
|
||||||
|
mSneakToggleShortcutTimer += dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
player.setSneak(mBindingsManager->actionIsActive(A_Sneak));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch"))
|
||||||
|
{
|
||||||
|
if (!mBindingsManager->actionIsActive(A_TogglePOV))
|
||||||
|
mGamepadZoom = 0;
|
||||||
|
|
||||||
|
if (mGamepadZoom)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->changeVanityModeScale(mGamepadZoom);
|
||||||
|
MWBase::Environment::get().getWorld()->setCameraDistance(mGamepadZoom, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return triedToMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg)
|
||||||
|
{
|
||||||
|
if (!mJoystickEnabled || mBindingsManager->isDetectingBindingState())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mJoystickLastUsed = true;
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
{
|
||||||
|
if (gamepadToGuiControl(arg))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mGamepadGuiCursorEnabled)
|
||||||
|
{
|
||||||
|
// Temporary mouse binding until keyboard controls are available:
|
||||||
|
if (arg.button == SDL_CONTROLLER_BUTTON_A) // We'll pretend that A is left click.
|
||||||
|
{
|
||||||
|
bool mousePressSuccess = mMouseManager->injectMouseButtonPress(SDL_BUTTON_LEFT);
|
||||||
|
if (MyGUI::InputManager::getInstance().getMouseFocusWidget())
|
||||||
|
{
|
||||||
|
MyGUI::Button* b = MyGUI::InputManager::getInstance().getMouseFocusWidget()->castType<MyGUI::Button>(false);
|
||||||
|
if (b && b->getEnabled())
|
||||||
|
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||||
|
}
|
||||||
|
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!mousePressSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(true);
|
||||||
|
|
||||||
|
//esc, to leave initial movie screen
|
||||||
|
auto kc = sdlKeyToMyGUI(SDLK_ESCAPE);
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyPress(kc, 0));
|
||||||
|
|
||||||
|
if (!MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
|
mBindingsManager->controllerButtonPressed(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg)
|
||||||
|
{
|
||||||
|
if (mBindingsManager->isDetectingBindingState())
|
||||||
|
{
|
||||||
|
mBindingsManager->controllerButtonReleased(deviceID, arg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mJoystickEnabled || MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mJoystickLastUsed = true;
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
{
|
||||||
|
if (mGamepadGuiCursorEnabled)
|
||||||
|
{
|
||||||
|
// Temporary mouse binding until keyboard controls are available:
|
||||||
|
if (arg.button == SDL_CONTROLLER_BUTTON_A) // We'll pretend that A is left click.
|
||||||
|
{
|
||||||
|
bool mousePressSuccess = mMouseManager->injectMouseButtonRelease(SDL_BUTTON_LEFT);
|
||||||
|
if (mBindingsManager->isDetectingBindingState()) // If the player just triggered binding, don't let button release bind.
|
||||||
|
return;
|
||||||
|
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!mousePressSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(true);
|
||||||
|
|
||||||
|
//esc, to leave initial movie screen
|
||||||
|
auto kc = sdlKeyToMyGUI(SDLK_ESCAPE);
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(kc));
|
||||||
|
|
||||||
|
mBindingsManager->controllerButtonReleased(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg)
|
||||||
|
{
|
||||||
|
if (!mJoystickEnabled || MWBase::Environment::get().getInputManager()->controlsDisabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mJoystickLastUsed = true;
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
{
|
||||||
|
gamepadToGuiControl(arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mGamepadPreviewMode && arg.value) // Preview Mode Gamepad Zooming
|
||||||
|
{
|
||||||
|
if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
|
||||||
|
{
|
||||||
|
mGamepadZoom = arg.value * 0.85f / 1000.f;
|
||||||
|
return; // Do not propagate event.
|
||||||
|
}
|
||||||
|
else if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
|
||||||
|
{
|
||||||
|
mGamepadZoom = -arg.value * 0.85f / 1000.f;
|
||||||
|
return; // Do not propagate event.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mBindingsManager->controllerAxisMoved(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg)
|
||||||
|
{
|
||||||
|
mBindingsManager->controllerAdded(deviceID, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControllerManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg)
|
||||||
|
{
|
||||||
|
mBindingsManager->controllerRemoved(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerManager::gamepadToGuiControl(const SDL_ControllerButtonEvent &arg)
|
||||||
|
{
|
||||||
|
// Presumption of GUI mode will be removed in the future.
|
||||||
|
// MyGUI KeyCodes *may* change.
|
||||||
|
MyGUI::KeyCode key = MyGUI::KeyCode::None;
|
||||||
|
switch (arg.button)
|
||||||
|
{
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||||
|
key = MyGUI::KeyCode::ArrowUp;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||||
|
key = MyGUI::KeyCode::ArrowRight;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||||
|
key = MyGUI::KeyCode::ArrowDown;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||||
|
key = MyGUI::KeyCode::ArrowLeft;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_A:
|
||||||
|
// If we are using the joystick as a GUI mouse, A must be handled via mouse.
|
||||||
|
if (mGamepadGuiCursorEnabled)
|
||||||
|
return false;
|
||||||
|
key = MyGUI::KeyCode::Space;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_B:
|
||||||
|
if (MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentModal();
|
||||||
|
else
|
||||||
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||||
|
return true;
|
||||||
|
case SDL_CONTROLLER_BUTTON_X:
|
||||||
|
key = MyGUI::KeyCode::Semicolon;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_Y:
|
||||||
|
key = MyGUI::KeyCode::Apostrophe;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||||
|
key = MyGUI::KeyCode::Period;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||||
|
key = MyGUI::KeyCode::Slash;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
||||||
|
mGamepadGuiCursorEnabled = !mGamepadGuiCursorEnabled;
|
||||||
|
MWBase::Environment::get().getWindowManager()->setCursorActive(mGamepadGuiCursorEnabled);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some keys will work even when Text Input windows/modals are in focus.
|
||||||
|
if (SDL_IsTextInputActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(key, 0, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerManager::gamepadToGuiControl(const SDL_ControllerAxisEvent &arg)
|
||||||
|
{
|
||||||
|
switch (arg.axis)
|
||||||
|
{
|
||||||
|
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||||
|
if (arg.value == 32767) // Treat like a button.
|
||||||
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Minus, 0, false);
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||||
|
if (arg.value == 32767) // Treat like a button.
|
||||||
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Equals, 0, false);
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||||
|
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||||
|
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||||
|
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||||
|
// If we are using the joystick as a GUI mouse, process mouse movement elsewhere.
|
||||||
|
if (mGamepadGuiCursorEnabled)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
65
apps/openmw/mwinput/controllermanager.hpp
Normal file
65
apps/openmw/mwinput/controllermanager.hpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef MWINPUT_MWCONTROLLERMANAGER_H
|
||||||
|
#define MWINPUT_MWCONTROLLERMANAGER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class ActionManager;
|
||||||
|
class BindingsManager;
|
||||||
|
class MouseManager;
|
||||||
|
|
||||||
|
class ControllerManager : public SDLUtil::ControllerListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControllerManager(BindingsManager* bindingsManager,
|
||||||
|
ActionManager* actionManager,
|
||||||
|
MouseManager* mouseManager,
|
||||||
|
const std::string& userControllerBindingsFile,
|
||||||
|
const std::string& controllerBindingsFile);
|
||||||
|
|
||||||
|
virtual ~ControllerManager() = default;
|
||||||
|
|
||||||
|
bool update(float dt);
|
||||||
|
|
||||||
|
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
|
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
|
virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg);
|
||||||
|
virtual void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg);
|
||||||
|
virtual void controllerRemoved(const SDL_ControllerDeviceEvent &arg);
|
||||||
|
|
||||||
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
void setJoystickLastUsed(bool enabled) { mJoystickLastUsed = enabled; }
|
||||||
|
bool joystickLastUsed() { return mJoystickLastUsed; }
|
||||||
|
|
||||||
|
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
|
||||||
|
|
||||||
|
void setGamepadGuiCursorEnabled(bool enabled) { mGamepadGuiCursorEnabled = enabled; }
|
||||||
|
bool gamepadGuiCursorEnabled() { return mGamepadGuiCursorEnabled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Return true if GUI consumes input.
|
||||||
|
bool gamepadToGuiControl(const SDL_ControllerButtonEvent &arg);
|
||||||
|
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
||||||
|
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
|
ActionManager* mActionManager;
|
||||||
|
MouseManager* mMouseManager;
|
||||||
|
|
||||||
|
bool mJoystickEnabled;
|
||||||
|
float mGamepadCursorSpeed;
|
||||||
|
float mInvUiScalingFactor;
|
||||||
|
float mSneakToggleShortcutTimer;
|
||||||
|
float mGamepadZoom;
|
||||||
|
bool mGamepadGuiCursorEnabled;
|
||||||
|
bool mJoystickLastUsed;
|
||||||
|
bool mGuiCursorEnabled;
|
||||||
|
bool mSneakGamepadShortcut;
|
||||||
|
bool mGamepadPreviewMode;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
99
apps/openmw/mwinput/controlswitch.cpp
Normal file
99
apps/openmw/mwinput/controlswitch.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#include "controlswitch.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/controlsstate.hpp>
|
||||||
|
|
||||||
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
ControlSwitch::ControlSwitch()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlSwitch::clear()
|
||||||
|
{
|
||||||
|
mSwitches["playercontrols"] = true;
|
||||||
|
mSwitches["playerfighting"] = true;
|
||||||
|
mSwitches["playerjumping"] = true;
|
||||||
|
mSwitches["playerlooking"] = true;
|
||||||
|
mSwitches["playermagic"] = true;
|
||||||
|
mSwitches["playerviewswitch"] = true;
|
||||||
|
mSwitches["vanitymode"] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControlSwitch::get(const std::string& key)
|
||||||
|
{
|
||||||
|
return mSwitches[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlSwitch::set(const std::string& key, bool value)
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
|
||||||
|
/// \note 7 switches at all, if-else is relevant
|
||||||
|
if (key == "playercontrols" && !value)
|
||||||
|
{
|
||||||
|
player.setLeftRight(0);
|
||||||
|
player.setForwardBackward(0);
|
||||||
|
player.setAutoMove(false);
|
||||||
|
player.setUpDown(0);
|
||||||
|
}
|
||||||
|
else if (key == "playerjumping" && !value)
|
||||||
|
{
|
||||||
|
/// \fixme maybe crouching at this time
|
||||||
|
player.setUpDown(0);
|
||||||
|
}
|
||||||
|
else if (key == "vanitymode")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->allowVanityMode(value);
|
||||||
|
}
|
||||||
|
else if (key == "playerlooking" && !value)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->rotateObject(player.getPlayer(), 0.f, 0.f, 0.f);
|
||||||
|
}
|
||||||
|
mSwitches[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlSwitch::write(ESM::ESMWriter& writer, Loading::Listener& /*progress*/)
|
||||||
|
{
|
||||||
|
ESM::ControlsState controls;
|
||||||
|
controls.mViewSwitchDisabled = !mSwitches["playerviewswitch"];
|
||||||
|
controls.mControlsDisabled = !mSwitches["playercontrols"];
|
||||||
|
controls.mJumpingDisabled = !mSwitches["playerjumping"];
|
||||||
|
controls.mLookingDisabled = !mSwitches["playerlooking"];
|
||||||
|
controls.mVanityModeDisabled = !mSwitches["vanitymode"];
|
||||||
|
controls.mWeaponDrawingDisabled = !mSwitches["playerfighting"];
|
||||||
|
controls.mSpellDrawingDisabled = !mSwitches["playermagic"];
|
||||||
|
|
||||||
|
writer.startRecord (ESM::REC_INPU);
|
||||||
|
controls.save(writer);
|
||||||
|
writer.endRecord (ESM::REC_INPU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlSwitch::readRecord(ESM::ESMReader& reader, uint32_t type)
|
||||||
|
{
|
||||||
|
ESM::ControlsState controls;
|
||||||
|
controls.load(reader);
|
||||||
|
|
||||||
|
set("playerviewswitch", !controls.mViewSwitchDisabled);
|
||||||
|
set("playercontrols", !controls.mControlsDisabled);
|
||||||
|
set("playerjumping", !controls.mJumpingDisabled);
|
||||||
|
set("playerlooking", !controls.mLookingDisabled);
|
||||||
|
set("vanitymode", !controls.mVanityModeDisabled);
|
||||||
|
set("playerfighting", !controls.mWeaponDrawingDisabled);
|
||||||
|
set("playermagic", !controls.mSpellDrawingDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ControlSwitch::countSavedGameRecords() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
38
apps/openmw/mwinput/controlswitch.hpp
Normal file
38
apps/openmw/mwinput/controlswitch.hpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef MWINPUT_CONTROLSWITCH_H
|
||||||
|
#define MWINPUT_CONTROLSWITCH_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct ControlsState;
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Loading
|
||||||
|
{
|
||||||
|
class Listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class ControlSwitch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlSwitch();
|
||||||
|
|
||||||
|
bool get(const std::string& key);
|
||||||
|
void set(const std::string& key, bool value);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
|
void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||||
|
int countSavedGameRecords() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, bool> mSwitches;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,18 @@
|
||||||
#ifndef MWINPUT_MWINPUTMANAGERIMP_H
|
#ifndef MWINPUT_MWINPUTMANAGERIMP_H
|
||||||
#define MWINPUT_MWINPUTMANAGERIMP_H
|
#define MWINPUT_MWINPUTMANAGERIMP_H
|
||||||
|
|
||||||
#include "../mwgui/mode.hpp"
|
|
||||||
|
|
||||||
#include <SDL_sensor.h>
|
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include <extern/oics/ICSChannelListener.h>
|
|
||||||
#include <extern/oics/ICSInputControlSystem.h>
|
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
|
||||||
#include <components/sdlutil/events.hpp>
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwgui/mode.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Player;
|
class Player;
|
||||||
|
@ -27,51 +23,27 @@ namespace MWBase
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ICS
|
|
||||||
{
|
|
||||||
class InputControlSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace MyGUI
|
|
||||||
{
|
|
||||||
struct MouseButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Files
|
|
||||||
{
|
|
||||||
struct ConfigurationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace SDLUtil
|
namespace SDLUtil
|
||||||
{
|
{
|
||||||
class InputWrapper;
|
class InputWrapper;
|
||||||
class VideoWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace osgViewer
|
|
||||||
{
|
|
||||||
class Viewer;
|
|
||||||
class ScreenCaptureHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SDL_Window;
|
struct SDL_Window;
|
||||||
|
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
const float ZOOM_SCALE = 120.f; /// Used for scrolling camera in and out
|
class ControlSwitch;
|
||||||
|
class ActionManager;
|
||||||
|
class BindingsManager;
|
||||||
|
class ControllerManager;
|
||||||
|
class KeyboardManager;
|
||||||
|
class MouseManager;
|
||||||
|
class SensorManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class that handles all input and key bindings for OpenMW.
|
* @brief Class that provides a high-level API for game input
|
||||||
*/
|
*/
|
||||||
class InputManager :
|
class InputManager : public MWBase::InputManager
|
||||||
public MWBase::InputManager,
|
|
||||||
public SDLUtil::KeyListener,
|
|
||||||
public SDLUtil::MouseListener,
|
|
||||||
public SDLUtil::SensorListener,
|
|
||||||
public SDLUtil::WindowListener,
|
|
||||||
public SDLUtil::ControllerListener,
|
|
||||||
public ICS::ChannelListener,
|
|
||||||
public ICS::DetectingBindingListener
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputManager(
|
InputManager(
|
||||||
|
@ -85,20 +57,18 @@ namespace MWInput
|
||||||
|
|
||||||
virtual ~InputManager();
|
virtual ~InputManager();
|
||||||
|
|
||||||
virtual bool isWindowVisible();
|
|
||||||
|
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
|
virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
|
||||||
|
|
||||||
void setPlayer (MWWorld::Player* player) { mPlayer = player; }
|
|
||||||
|
|
||||||
virtual void changeInputMode(bool guiMode);
|
virtual void changeInputMode(bool guiMode);
|
||||||
|
|
||||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
|
virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
virtual void setDragDrop(bool dragDrop);
|
virtual void setDragDrop(bool dragDrop);
|
||||||
|
virtual void setGamepadGuiCursorEnabled(bool enabled);
|
||||||
|
virtual void setAttemptJump(bool jumping);
|
||||||
|
|
||||||
virtual void toggleControlSwitch (const std::string& sw, bool value);
|
virtual void toggleControlSwitch (const std::string& sw, bool value);
|
||||||
virtual bool getControlSwitch (const std::string& sw);
|
virtual bool getControlSwitch (const std::string& sw);
|
||||||
|
@ -113,264 +83,42 @@ namespace MWInput
|
||||||
virtual void resetToDefaultKeyBindings();
|
virtual void resetToDefaultKeyBindings();
|
||||||
virtual void resetToDefaultControllerBindings();
|
virtual void resetToDefaultControllerBindings();
|
||||||
|
|
||||||
virtual bool joystickLastUsed() {return mJoystickLastUsed;}
|
virtual void setJoystickLastUsed(bool enabled);
|
||||||
|
virtual bool joystickLastUsed();
|
||||||
public:
|
|
||||||
virtual void keyPressed(const SDL_KeyboardEvent &arg );
|
|
||||||
virtual void keyReleased( const SDL_KeyboardEvent &arg );
|
|
||||||
virtual void textInput (const SDL_TextInputEvent &arg);
|
|
||||||
|
|
||||||
virtual void mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id );
|
|
||||||
virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
|
|
||||||
virtual void mouseMoved( const SDLUtil::MouseMotionEvent &arg );
|
|
||||||
|
|
||||||
virtual void mouseWheelMoved( const SDL_MouseWheelEvent &arg);
|
|
||||||
|
|
||||||
virtual void sensorUpdated(const SDL_SensorEvent &arg);
|
|
||||||
virtual void displayOrientationChanged();
|
|
||||||
|
|
||||||
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
|
||||||
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
|
||||||
virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg);
|
|
||||||
virtual void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg);
|
|
||||||
virtual void controllerRemoved(const SDL_ControllerDeviceEvent &arg);
|
|
||||||
|
|
||||||
virtual void windowVisibilityChange( bool visible );
|
|
||||||
virtual void windowFocusChange( bool have_focus );
|
|
||||||
virtual void windowResized (int x, int y);
|
|
||||||
virtual void windowClosed ();
|
|
||||||
|
|
||||||
virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue);
|
|
||||||
|
|
||||||
virtual void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
|
||||||
, SDL_Scancode key, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
|
||||||
, ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
|
||||||
, unsigned int button, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
virtual void mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
|
|
||||||
, ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control
|
|
||||||
, int axis, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control
|
|
||||||
, unsigned int button, ICS::Control::ControlChangingDirection direction);
|
|
||||||
|
|
||||||
void clearAllKeyBindings (ICS::Control* control);
|
|
||||||
void clearAllControllerBindings (ICS::Control* control);
|
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const;
|
virtual int countSavedGameRecords() const;
|
||||||
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||||
|
|
||||||
private:
|
virtual void resetIdleTime();
|
||||||
enum GyroscopeAxis
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
X = 1,
|
|
||||||
Y = 2,
|
|
||||||
Z = 3,
|
|
||||||
Minus_X = -1,
|
|
||||||
Minus_Y = -2,
|
|
||||||
Minus_Z = -3
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_Window* mWindow;
|
virtual void executeAction(int action);
|
||||||
bool mWindowVisible;
|
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
|
||||||
osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation;
|
|
||||||
|
|
||||||
bool mJoystickLastUsed;
|
virtual bool controlsDisabled() { return mControlsDisabled; }
|
||||||
MWWorld::Player* mPlayer;
|
|
||||||
|
|
||||||
ICS::InputControlSystem* mInputBinder;
|
|
||||||
|
|
||||||
SDLUtil::InputWrapper* mInputManager;
|
|
||||||
SDLUtil::VideoWrapper* mVideoWrapper;
|
|
||||||
|
|
||||||
std::string mUserFile;
|
|
||||||
|
|
||||||
bool mDragDrop;
|
|
||||||
|
|
||||||
bool mGrabCursor;
|
|
||||||
|
|
||||||
bool mInvertX;
|
|
||||||
bool mInvertY;
|
|
||||||
|
|
||||||
bool mControlsDisabled;
|
|
||||||
bool mJoystickEnabled;
|
|
||||||
|
|
||||||
float mCameraSensitivity;
|
|
||||||
float mCameraYMultiplier;
|
|
||||||
float mPreviewPOVDelay;
|
|
||||||
float mTimeIdle;
|
|
||||||
|
|
||||||
bool mMouseLookEnabled;
|
|
||||||
bool mGuiCursorEnabled;
|
|
||||||
bool mGamepadGuiCursorEnabled;
|
|
||||||
|
|
||||||
bool mDetectingKeyboard;
|
|
||||||
|
|
||||||
float mOverencumberedMessageDelay;
|
|
||||||
|
|
||||||
float mGuiCursorX;
|
|
||||||
float mGuiCursorY;
|
|
||||||
int mMouseWheel;
|
|
||||||
float mGamepadZoom;
|
|
||||||
bool mUserFileExists;
|
|
||||||
bool mAlwaysRunActive;
|
|
||||||
bool mSneakToggles;
|
|
||||||
float mSneakToggleShortcutTimer;
|
|
||||||
bool mSneakGamepadShortcut;
|
|
||||||
bool mSneaking;
|
|
||||||
bool mAttemptJump;
|
|
||||||
|
|
||||||
std::map<std::string, bool> mControlSwitch;
|
|
||||||
|
|
||||||
float mInvUiScalingFactor;
|
|
||||||
float mGamepadCursorSpeed;
|
|
||||||
|
|
||||||
float mGyroXSpeed;
|
|
||||||
float mGyroYSpeed;
|
|
||||||
float mGyroUpdateTimer;
|
|
||||||
|
|
||||||
float mGyroHSensitivity;
|
|
||||||
float mGyroVSensitivity;
|
|
||||||
GyroscopeAxis mGyroHAxis;
|
|
||||||
GyroscopeAxis mGyroVAxis;
|
|
||||||
float mGyroInputThreshold;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void convertMousePosForMyGUI(int& x, int& y);
|
void convertMousePosForMyGUI(int& x, int& y);
|
||||||
|
|
||||||
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
|
||||||
|
|
||||||
virtual std::string sdlControllerAxisToString(int axis);
|
|
||||||
virtual std::string sdlControllerButtonToString(int button);
|
|
||||||
|
|
||||||
void resetIdleTime();
|
|
||||||
void updateIdleTime(float dt);
|
|
||||||
|
|
||||||
void setPlayerControlsEnabled(bool enabled);
|
|
||||||
void handleGuiArrowKey(int action);
|
void handleGuiArrowKey(int action);
|
||||||
// Return true if GUI consumes input.
|
|
||||||
bool gamepadToGuiControl(const SDL_ControllerButtonEvent &arg);
|
|
||||||
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
|
||||||
|
|
||||||
void updateCursorMode();
|
void quickKey(int index);
|
||||||
void updateSensors();
|
|
||||||
void correctGyroscopeAxes();
|
|
||||||
GyroscopeAxis mapGyroscopeAxis(const std::string& axis);
|
|
||||||
|
|
||||||
bool checkAllowedToUseItems() const;
|
|
||||||
|
|
||||||
float getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void toggleMainMenu();
|
|
||||||
void toggleSpell();
|
|
||||||
void toggleWeapon();
|
|
||||||
void toggleInventory();
|
|
||||||
void toggleConsole();
|
|
||||||
void screenshot();
|
|
||||||
void toggleJournal();
|
|
||||||
void activate();
|
|
||||||
void toggleWalking();
|
|
||||||
void toggleSneaking();
|
|
||||||
void toggleAutoMove();
|
|
||||||
void rest();
|
|
||||||
void quickLoad();
|
|
||||||
void quickSave();
|
|
||||||
|
|
||||||
void quickKey (int index);
|
|
||||||
void showQuickKeysMenu();
|
void showQuickKeysMenu();
|
||||||
|
|
||||||
bool actionIsActive (int id);
|
|
||||||
|
|
||||||
void loadKeyDefaults(bool force = false);
|
void loadKeyDefaults(bool force = false);
|
||||||
void loadControllerDefaults(bool force = false);
|
void loadControllerDefaults(bool force = false);
|
||||||
|
|
||||||
int mFakeDeviceID; //As we only support one controller at a time, use a fake deviceID so we don't lose bindings when switching controllers
|
SDLUtil::InputWrapper* mInputWrapper;
|
||||||
SDL_Sensor* mGyroscope;
|
|
||||||
|
|
||||||
private:
|
bool mControlsDisabled;
|
||||||
enum Actions
|
|
||||||
{
|
|
||||||
// please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files
|
|
||||||
|
|
||||||
A_GameMenu,
|
ControlSwitch* mControlSwitch;
|
||||||
|
|
||||||
A_Unused,
|
ActionManager* mActionManager;
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
A_Screenshot, // Take a screenshot
|
ControllerManager* mControllerManager;
|
||||||
|
KeyboardManager* mKeyboardManager;
|
||||||
A_Inventory, // Toggle inventory screen
|
MouseManager* mMouseManager;
|
||||||
|
SensorManager* mSensorManager;
|
||||||
A_Console, // Toggle console screen
|
|
||||||
|
|
||||||
A_MoveLeft, // Move player left / right
|
|
||||||
A_MoveRight,
|
|
||||||
A_MoveForward, // Forward / Backward
|
|
||||||
A_MoveBackward,
|
|
||||||
|
|
||||||
A_Activate,
|
|
||||||
|
|
||||||
A_Use, //Use weapon, spell, etc.
|
|
||||||
A_Jump,
|
|
||||||
A_AutoMove, //Toggle Auto-move forward
|
|
||||||
A_Rest, //Rest
|
|
||||||
A_Journal, //Journal
|
|
||||||
A_Weapon, //Draw/Sheath weapon
|
|
||||||
A_Spell, //Ready/Unready Casting
|
|
||||||
A_Run, //Run when held
|
|
||||||
A_CycleSpellLeft, //cycling through spells
|
|
||||||
A_CycleSpellRight,
|
|
||||||
A_CycleWeaponLeft, //Cycling through weapons
|
|
||||||
A_CycleWeaponRight,
|
|
||||||
A_ToggleSneak, //Toggles Sneak
|
|
||||||
A_AlwaysRun, //Toggle Walking/Running
|
|
||||||
A_Sneak,
|
|
||||||
|
|
||||||
A_QuickSave,
|
|
||||||
A_QuickLoad,
|
|
||||||
A_QuickMenu,
|
|
||||||
A_ToggleWeapon,
|
|
||||||
A_ToggleSpell,
|
|
||||||
|
|
||||||
A_TogglePOV,
|
|
||||||
|
|
||||||
A_QuickKey1,
|
|
||||||
A_QuickKey2,
|
|
||||||
A_QuickKey3,
|
|
||||||
A_QuickKey4,
|
|
||||||
A_QuickKey5,
|
|
||||||
A_QuickKey6,
|
|
||||||
A_QuickKey7,
|
|
||||||
A_QuickKey8,
|
|
||||||
A_QuickKey9,
|
|
||||||
A_QuickKey10,
|
|
||||||
|
|
||||||
A_QuickKeysMenu,
|
|
||||||
|
|
||||||
A_ToggleHUD,
|
|
||||||
|
|
||||||
A_ToggleDebug,
|
|
||||||
|
|
||||||
A_LookUpDown, //Joystick look
|
|
||||||
A_LookLeftRight,
|
|
||||||
A_MoveForwardBackward,
|
|
||||||
A_MoveLeftRight,
|
|
||||||
|
|
||||||
A_ZoomIn,
|
|
||||||
A_ZoomOut,
|
|
||||||
|
|
||||||
A_Last // Marker for the last item
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
71
apps/openmw/mwinput/keyboardmanager.cpp
Normal file
71
apps/openmw/mwinput/keyboardmanager.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#include "keyboardmanager.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
#include "bindingsmanager.hpp"
|
||||||
|
#include "sdlmappings.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
KeyboardManager::KeyboardManager(BindingsManager* bindingsManager)
|
||||||
|
: mBindingsManager(bindingsManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardManager::textInput(const SDL_TextInputEvent &arg)
|
||||||
|
{
|
||||||
|
MyGUI::UString ustring(&arg.text[0]);
|
||||||
|
MyGUI::UString::utf32string utf32string = ustring.asUTF32();
|
||||||
|
for (MyGUI::UString::utf32string::const_iterator it = utf32string.begin(); it != utf32string.end(); ++it)
|
||||||
|
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::None, *it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardManager::keyPressed(const SDL_KeyboardEvent &arg)
|
||||||
|
{
|
||||||
|
// HACK: to make default keybinding for the console work without printing an extra "^" upon closing
|
||||||
|
// This assumes that SDL_TextInput events always come *after* the key event
|
||||||
|
// (which is somewhat reasonable, and hopefully true for all SDL platforms)
|
||||||
|
auto kc = sdlKeyToMyGUI(arg.keysym.sym);
|
||||||
|
if (mBindingsManager->getKeyBinding(A_Console) == arg.keysym.scancode
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||||
|
SDL_StopTextInput();
|
||||||
|
|
||||||
|
bool consumed = false;
|
||||||
|
if (kc != MyGUI::KeyCode::None && !mBindingsManager->isDetectingBindingState())
|
||||||
|
{
|
||||||
|
consumed = MWBase::Environment::get().getWindowManager()->injectKeyPress(kc, 0, arg.repeat);
|
||||||
|
if (SDL_IsTextInputActive() && // Little trick to check if key is printable
|
||||||
|
(!(SDLK_SCANCODE_MASK & arg.keysym.sym) && std::isprint(arg.keysym.sym)))
|
||||||
|
consumed = true;
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!consumed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.repeat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
|
||||||
|
if (!input->controlsDisabled() && !consumed)
|
||||||
|
mBindingsManager->keyPressed(arg);
|
||||||
|
|
||||||
|
input->setJoystickLastUsed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardManager::keyReleased(const SDL_KeyboardEvent &arg)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getInputManager()->setJoystickLastUsed(false);
|
||||||
|
auto kc = sdlKeyToMyGUI(arg.keysym.sym);
|
||||||
|
|
||||||
|
if (!mBindingsManager->isDetectingBindingState())
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(kc));
|
||||||
|
mBindingsManager->keyReleased(arg);
|
||||||
|
}
|
||||||
|
}
|
26
apps/openmw/mwinput/keyboardmanager.hpp
Normal file
26
apps/openmw/mwinput/keyboardmanager.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef MWINPUT_MWKEYBOARDMANAGER_H
|
||||||
|
#define MWINPUT_MWKEYBOARDMANAGER_H
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class BindingsManager;
|
||||||
|
|
||||||
|
class KeyboardManager : public SDLUtil::KeyListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyboardManager(BindingsManager* bindingsManager);
|
||||||
|
|
||||||
|
virtual ~KeyboardManager() = default;
|
||||||
|
|
||||||
|
virtual void textInput(const SDL_TextInputEvent &arg);
|
||||||
|
virtual void keyPressed(const SDL_KeyboardEvent &arg);
|
||||||
|
virtual void keyReleased(const SDL_KeyboardEvent &arg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
252
apps/openmw/mwinput/mousemanager.cpp
Normal file
252
apps/openmw/mwinput/mousemanager.cpp
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
#include "mousemanager.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/sdlutil/sdlinputwrapper.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "actions.hpp"
|
||||||
|
#include "bindingsmanager.hpp"
|
||||||
|
#include "sdlmappings.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
MouseManager::MouseManager(BindingsManager* bindingsManager, SDLUtil::InputWrapper* inputWrapper, SDL_Window* window)
|
||||||
|
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
||||||
|
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
||||||
|
, mGrabCursor(Settings::Manager::getBool("grab cursor", "Input"))
|
||||||
|
, mCameraSensitivity(Settings::Manager::getFloat("camera sensitivity", "Input"))
|
||||||
|
, mCameraYMultiplier(Settings::Manager::getFloat("camera y multiplier", "Input"))
|
||||||
|
, mBindingsManager(bindingsManager)
|
||||||
|
, mInputWrapper(inputWrapper)
|
||||||
|
, mInvUiScalingFactor(1.f)
|
||||||
|
, mGuiCursorX(0)
|
||||||
|
, mGuiCursorY(0)
|
||||||
|
, mMouseWheel(0)
|
||||||
|
, mMouseLookEnabled(false)
|
||||||
|
, mGuiCursorEnabled(true)
|
||||||
|
{
|
||||||
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
|
if (uiScale != 0.f)
|
||||||
|
mInvUiScalingFactor = 1.f / uiScale;
|
||||||
|
|
||||||
|
int w,h;
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
|
||||||
|
mGuiCursorX = mInvUiScalingFactor * w / 2.f;
|
||||||
|
mGuiCursorY = mInvUiScalingFactor * h / 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
|
{
|
||||||
|
for (const auto& setting : changed)
|
||||||
|
{
|
||||||
|
if (setting.first == "Input" && setting.second == "invert x axis")
|
||||||
|
mInvertX = Settings::Manager::getBool("invert x axis", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "invert y axis")
|
||||||
|
mInvertY = Settings::Manager::getBool("invert y axis", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "camera sensitivity")
|
||||||
|
mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "grab cursor")
|
||||||
|
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::mouseMoved(const SDLUtil::MouseMotionEvent &arg)
|
||||||
|
{
|
||||||
|
mBindingsManager->mouseMoved(arg);
|
||||||
|
|
||||||
|
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
|
||||||
|
input->setJoystickLastUsed(false);
|
||||||
|
input->resetIdleTime();
|
||||||
|
|
||||||
|
if (mGuiCursorEnabled)
|
||||||
|
{
|
||||||
|
input->setGamepadGuiCursorEnabled(true);
|
||||||
|
|
||||||
|
// We keep track of our own mouse position, so that moving the mouse while in
|
||||||
|
// game mode does not move the position of the GUI cursor
|
||||||
|
mGuiCursorX = static_cast<float>(arg.x) * mInvUiScalingFactor;
|
||||||
|
mGuiCursorY = static_cast<float>(arg.y) * mInvUiScalingFactor;
|
||||||
|
|
||||||
|
mMouseWheel = static_cast<int>(arg.z);
|
||||||
|
|
||||||
|
MyGUI::InputManager::getInstance().injectMouseMove(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), mMouseWheel);
|
||||||
|
// FIXME: inject twice to force updating focused widget states (tooltips) resulting from changing the viewport by scroll wheel
|
||||||
|
MyGUI::InputManager::getInstance().injectMouseMove(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), mMouseWheel);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->setCursorActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMouseLookEnabled && !input->controlsDisabled())
|
||||||
|
{
|
||||||
|
float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
||||||
|
float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
||||||
|
|
||||||
|
float rot[3];
|
||||||
|
rot[0] = -y;
|
||||||
|
rot[1] = 0.0f;
|
||||||
|
rot[2] = -x;
|
||||||
|
|
||||||
|
// Only actually turn player when we're not in vanity mode
|
||||||
|
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && input->getControlSwitch("playerlooking"))
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.yaw(x);
|
||||||
|
player.pitch(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.zrel && input->getControlSwitch("playerviewswitch") && input->getControlSwitch("playercontrols")) //Check to make sure you are allowed to zoomout and there is a change
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->changeVanityModeScale(static_cast<float>(arg.zrel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::mouseReleased(const SDL_MouseButtonEvent &arg, Uint8 id)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getInputManager()->setJoystickLastUsed(false);
|
||||||
|
|
||||||
|
if (mBindingsManager->isDetectingBindingState())
|
||||||
|
{
|
||||||
|
mBindingsManager->mouseReleased(arg, id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), sdlButtonToMyGUI(id)) && guiMode;
|
||||||
|
|
||||||
|
if (mBindingsManager->isDetectingBindingState())
|
||||||
|
return; // don't allow same mouseup to bind as initiated bind
|
||||||
|
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!guiMode);
|
||||||
|
mBindingsManager->mouseReleased(arg, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::mouseWheelMoved(const SDL_MouseWheelEvent &arg)
|
||||||
|
{
|
||||||
|
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
|
||||||
|
if (mBindingsManager->isDetectingBindingState() || !input->controlsDisabled())
|
||||||
|
mBindingsManager->mouseWheelMoved(arg);
|
||||||
|
|
||||||
|
input->setJoystickLastUsed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getInputManager()->setJoystickLastUsed(false);
|
||||||
|
bool guiMode = false;
|
||||||
|
|
||||||
|
if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events
|
||||||
|
{
|
||||||
|
guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
|
||||||
|
guiMode = MyGUI::InputManager::getInstance().injectMousePress(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), sdlButtonToMyGUI(id)) && guiMode;
|
||||||
|
if (MyGUI::InputManager::getInstance().getMouseFocusWidget () != 0)
|
||||||
|
{
|
||||||
|
MyGUI::Button* b = MyGUI::InputManager::getInstance().getMouseFocusWidget()->castType<MyGUI::Button>(false);
|
||||||
|
if (b && b->getEnabled() && id == SDL_BUTTON_LEFT)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MWBase::Environment::get().getWindowManager()->setCursorActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mBindingsManager->setPlayerControlsEnabled(!guiMode);
|
||||||
|
|
||||||
|
// Don't trigger any mouse bindings while in settings menu, otherwise rebinding controls becomes impossible
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Settings)
|
||||||
|
mBindingsManager->mousePressed(arg, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::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)
|
||||||
|
{
|
||||||
|
warpMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::update(float dt)
|
||||||
|
{
|
||||||
|
if (!mMouseLookEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float xAxis = mBindingsManager->getActionValue(A_LookLeftRight) * 2.0f - 1.0f;
|
||||||
|
float yAxis = mBindingsManager->getActionValue(A_LookUpDown) * 2.0f - 1.0f;
|
||||||
|
if (xAxis == 0 && yAxis == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float rot[3];
|
||||||
|
rot[0] = yAxis * dt * 1000.0f * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f;
|
||||||
|
rot[1] = 0.0f;
|
||||||
|
rot[2] = xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f;
|
||||||
|
|
||||||
|
// Only actually turn player when we're not in vanity mode
|
||||||
|
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.yaw(rot[2]);
|
||||||
|
player.pitch(rot[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MouseManager::injectMouseButtonPress(Uint8 button)
|
||||||
|
{
|
||||||
|
return MyGUI::InputManager::getInstance().injectMousePress(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), sdlButtonToMyGUI(button));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MouseManager::injectMouseButtonRelease(Uint8 button)
|
||||||
|
{
|
||||||
|
return MyGUI::InputManager::getInstance().injectMousePress(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), sdlButtonToMyGUI(button));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::injectMouseMove(int xMove, int yMove, int mouseWheelMove)
|
||||||
|
{
|
||||||
|
mGuiCursorX += xMove;
|
||||||
|
mGuiCursorY += yMove;
|
||||||
|
mMouseWheel += mouseWheelMove;
|
||||||
|
|
||||||
|
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
|
mGuiCursorX = std::max(0.f, std::min(mGuiCursorX, float(viewSize.width - 1)));
|
||||||
|
mGuiCursorY = std::max(0.f, std::min(mGuiCursorY, float(viewSize.height - 1)));
|
||||||
|
|
||||||
|
MyGUI::InputManager::getInstance().injectMouseMove(static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), mMouseWheel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseManager::warpMouse()
|
||||||
|
{
|
||||||
|
mInputWrapper->warpMouse(static_cast<int>(mGuiCursorX / mInvUiScalingFactor), static_cast<int>(mGuiCursorY / mInvUiScalingFactor));
|
||||||
|
}
|
||||||
|
}
|
59
apps/openmw/mwinput/mousemanager.hpp
Normal file
59
apps/openmw/mwinput/mousemanager.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef MWINPUT_MWMOUSEMANAGER_H
|
||||||
|
#define MWINPUT_MWMOUSEMANAGER_H
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace SDLUtil
|
||||||
|
{
|
||||||
|
class InputWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class BindingsManager;
|
||||||
|
|
||||||
|
class MouseManager : public SDLUtil::MouseListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MouseManager(BindingsManager* bindingsManager, SDLUtil::InputWrapper* inputWrapper, SDL_Window* window);
|
||||||
|
|
||||||
|
virtual ~MouseManager() = default;
|
||||||
|
|
||||||
|
void updateCursorMode();
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
|
virtual void mouseMoved(const SDLUtil::MouseMotionEvent &arg);
|
||||||
|
virtual void mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id);
|
||||||
|
virtual void mouseReleased(const SDL_MouseButtonEvent &arg, Uint8 id);
|
||||||
|
virtual void mouseWheelMoved(const SDL_MouseWheelEvent &arg);
|
||||||
|
|
||||||
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
bool injectMouseButtonPress(Uint8 button);
|
||||||
|
bool injectMouseButtonRelease(Uint8 button);
|
||||||
|
void injectMouseMove(int xMove, int yMove, int mouseWheelMove);
|
||||||
|
void warpMouse();
|
||||||
|
|
||||||
|
void setMouseLookEnabled(bool enabled) { mMouseLookEnabled = enabled; }
|
||||||
|
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mInvertX;
|
||||||
|
bool mInvertY;
|
||||||
|
bool mGrabCursor;
|
||||||
|
float mCameraSensitivity;
|
||||||
|
float mCameraYMultiplier;
|
||||||
|
|
||||||
|
BindingsManager* mBindingsManager;
|
||||||
|
SDLUtil::InputWrapper* mInputWrapper;
|
||||||
|
float mInvUiScalingFactor;
|
||||||
|
|
||||||
|
float mGuiCursorX;
|
||||||
|
float mGuiCursorY;
|
||||||
|
int mMouseWheel;
|
||||||
|
bool mMouseLookEnabled;
|
||||||
|
bool mGuiCursorEnabled;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
218
apps/openmw/mwinput/sdlmappings.cpp
Normal file
218
apps/openmw/mwinput/sdlmappings.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
#include "sdlmappings.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <MyGUI_MouseButton.h>
|
||||||
|
|
||||||
|
#include <SDL_gamecontroller.h>
|
||||||
|
#include <SDL_mouse.h>
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
std::string sdlControllerButtonToString(int button)
|
||||||
|
{
|
||||||
|
switch(button)
|
||||||
|
{
|
||||||
|
case SDL_CONTROLLER_BUTTON_A:
|
||||||
|
return "A Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_B:
|
||||||
|
return "B Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_BACK:
|
||||||
|
return "Back Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||||
|
return "DPad Down";
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||||
|
return "DPad Left";
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||||
|
return "DPad Right";
|
||||||
|
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||||
|
return "DPad Up";
|
||||||
|
case SDL_CONTROLLER_BUTTON_GUIDE:
|
||||||
|
return "Guide Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||||
|
return "Left Shoulder";
|
||||||
|
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
||||||
|
return "Left Stick Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||||
|
return "Right Shoulder";
|
||||||
|
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||||
|
return "Right Stick Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_START:
|
||||||
|
return "Start Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_X:
|
||||||
|
return "X Button";
|
||||||
|
case SDL_CONTROLLER_BUTTON_Y:
|
||||||
|
return "Y Button";
|
||||||
|
default:
|
||||||
|
return "Button " + std::to_string(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sdlControllerAxisToString(int axis)
|
||||||
|
{
|
||||||
|
switch(axis)
|
||||||
|
{
|
||||||
|
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||||
|
return "Left Stick X";
|
||||||
|
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||||
|
return "Left Stick Y";
|
||||||
|
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||||
|
return "Right Stick X";
|
||||||
|
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||||
|
return "Right Stick Y";
|
||||||
|
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||||
|
return "Left Trigger";
|
||||||
|
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||||
|
return "Right Trigger";
|
||||||
|
default:
|
||||||
|
return "Axis " + std::to_string(axis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button)
|
||||||
|
{
|
||||||
|
//The right button is the second button, according to MyGUI
|
||||||
|
if(button == SDL_BUTTON_RIGHT)
|
||||||
|
button = SDL_BUTTON_MIDDLE;
|
||||||
|
else if(button == SDL_BUTTON_MIDDLE)
|
||||||
|
button = SDL_BUTTON_RIGHT;
|
||||||
|
|
||||||
|
//MyGUI's buttons are 0 indexed
|
||||||
|
return MyGUI::MouseButton::Enum(button - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initKeyMap(std::map<SDL_Keycode, MyGUI::KeyCode>& keyMap)
|
||||||
|
{
|
||||||
|
keyMap[SDLK_UNKNOWN] = MyGUI::KeyCode::None;
|
||||||
|
keyMap[SDLK_ESCAPE] = MyGUI::KeyCode::Escape;
|
||||||
|
keyMap[SDLK_1] = MyGUI::KeyCode::One;
|
||||||
|
keyMap[SDLK_2] = MyGUI::KeyCode::Two;
|
||||||
|
keyMap[SDLK_3] = MyGUI::KeyCode::Three;
|
||||||
|
keyMap[SDLK_4] = MyGUI::KeyCode::Four;
|
||||||
|
keyMap[SDLK_5] = MyGUI::KeyCode::Five;
|
||||||
|
keyMap[SDLK_6] = MyGUI::KeyCode::Six;
|
||||||
|
keyMap[SDLK_7] = MyGUI::KeyCode::Seven;
|
||||||
|
keyMap[SDLK_8] = MyGUI::KeyCode::Eight;
|
||||||
|
keyMap[SDLK_9] = MyGUI::KeyCode::Nine;
|
||||||
|
keyMap[SDLK_0] = MyGUI::KeyCode::Zero;
|
||||||
|
keyMap[SDLK_MINUS] = MyGUI::KeyCode::Minus;
|
||||||
|
keyMap[SDLK_EQUALS] = MyGUI::KeyCode::Equals;
|
||||||
|
keyMap[SDLK_BACKSPACE] = MyGUI::KeyCode::Backspace;
|
||||||
|
keyMap[SDLK_TAB] = MyGUI::KeyCode::Tab;
|
||||||
|
keyMap[SDLK_q] = MyGUI::KeyCode::Q;
|
||||||
|
keyMap[SDLK_w] = MyGUI::KeyCode::W;
|
||||||
|
keyMap[SDLK_e] = MyGUI::KeyCode::E;
|
||||||
|
keyMap[SDLK_r] = MyGUI::KeyCode::R;
|
||||||
|
keyMap[SDLK_t] = MyGUI::KeyCode::T;
|
||||||
|
keyMap[SDLK_y] = MyGUI::KeyCode::Y;
|
||||||
|
keyMap[SDLK_u] = MyGUI::KeyCode::U;
|
||||||
|
keyMap[SDLK_i] = MyGUI::KeyCode::I;
|
||||||
|
keyMap[SDLK_o] = MyGUI::KeyCode::O;
|
||||||
|
keyMap[SDLK_p] = MyGUI::KeyCode::P;
|
||||||
|
keyMap[SDLK_RETURN] = MyGUI::KeyCode::Return;
|
||||||
|
keyMap[SDLK_a] = MyGUI::KeyCode::A;
|
||||||
|
keyMap[SDLK_s] = MyGUI::KeyCode::S;
|
||||||
|
keyMap[SDLK_d] = MyGUI::KeyCode::D;
|
||||||
|
keyMap[SDLK_f] = MyGUI::KeyCode::F;
|
||||||
|
keyMap[SDLK_g] = MyGUI::KeyCode::G;
|
||||||
|
keyMap[SDLK_h] = MyGUI::KeyCode::H;
|
||||||
|
keyMap[SDLK_j] = MyGUI::KeyCode::J;
|
||||||
|
keyMap[SDLK_k] = MyGUI::KeyCode::K;
|
||||||
|
keyMap[SDLK_l] = MyGUI::KeyCode::L;
|
||||||
|
keyMap[SDLK_SEMICOLON] = MyGUI::KeyCode::Semicolon;
|
||||||
|
keyMap[SDLK_QUOTE] = MyGUI::KeyCode::Apostrophe;
|
||||||
|
keyMap[SDLK_BACKQUOTE] = MyGUI::KeyCode::Grave;
|
||||||
|
keyMap[SDLK_LSHIFT] = MyGUI::KeyCode::LeftShift;
|
||||||
|
keyMap[SDLK_BACKSLASH] = MyGUI::KeyCode::Backslash;
|
||||||
|
keyMap[SDLK_z] = MyGUI::KeyCode::Z;
|
||||||
|
keyMap[SDLK_x] = MyGUI::KeyCode::X;
|
||||||
|
keyMap[SDLK_c] = MyGUI::KeyCode::C;
|
||||||
|
keyMap[SDLK_v] = MyGUI::KeyCode::V;
|
||||||
|
keyMap[SDLK_b] = MyGUI::KeyCode::B;
|
||||||
|
keyMap[SDLK_n] = MyGUI::KeyCode::N;
|
||||||
|
keyMap[SDLK_m] = MyGUI::KeyCode::M;
|
||||||
|
keyMap[SDLK_COMMA] = MyGUI::KeyCode::Comma;
|
||||||
|
keyMap[SDLK_PERIOD] = MyGUI::KeyCode::Period;
|
||||||
|
keyMap[SDLK_SLASH] = MyGUI::KeyCode::Slash;
|
||||||
|
keyMap[SDLK_RSHIFT] = MyGUI::KeyCode::RightShift;
|
||||||
|
keyMap[SDLK_KP_MULTIPLY] = MyGUI::KeyCode::Multiply;
|
||||||
|
keyMap[SDLK_LALT] = MyGUI::KeyCode::LeftAlt;
|
||||||
|
keyMap[SDLK_SPACE] = MyGUI::KeyCode::Space;
|
||||||
|
keyMap[SDLK_CAPSLOCK] = MyGUI::KeyCode::Capital;
|
||||||
|
keyMap[SDLK_F1] = MyGUI::KeyCode::F1;
|
||||||
|
keyMap[SDLK_F2] = MyGUI::KeyCode::F2;
|
||||||
|
keyMap[SDLK_F3] = MyGUI::KeyCode::F3;
|
||||||
|
keyMap[SDLK_F4] = MyGUI::KeyCode::F4;
|
||||||
|
keyMap[SDLK_F5] = MyGUI::KeyCode::F5;
|
||||||
|
keyMap[SDLK_F6] = MyGUI::KeyCode::F6;
|
||||||
|
keyMap[SDLK_F7] = MyGUI::KeyCode::F7;
|
||||||
|
keyMap[SDLK_F8] = MyGUI::KeyCode::F8;
|
||||||
|
keyMap[SDLK_F9] = MyGUI::KeyCode::F9;
|
||||||
|
keyMap[SDLK_F10] = MyGUI::KeyCode::F10;
|
||||||
|
keyMap[SDLK_NUMLOCKCLEAR] = MyGUI::KeyCode::NumLock;
|
||||||
|
keyMap[SDLK_SCROLLLOCK] = MyGUI::KeyCode::ScrollLock;
|
||||||
|
keyMap[SDLK_KP_7] = MyGUI::KeyCode::Numpad7;
|
||||||
|
keyMap[SDLK_KP_8] = MyGUI::KeyCode::Numpad8;
|
||||||
|
keyMap[SDLK_KP_9] = MyGUI::KeyCode::Numpad9;
|
||||||
|
keyMap[SDLK_KP_MINUS] = MyGUI::KeyCode::Subtract;
|
||||||
|
keyMap[SDLK_KP_4] = MyGUI::KeyCode::Numpad4;
|
||||||
|
keyMap[SDLK_KP_5] = MyGUI::KeyCode::Numpad5;
|
||||||
|
keyMap[SDLK_KP_6] = MyGUI::KeyCode::Numpad6;
|
||||||
|
keyMap[SDLK_KP_PLUS] = MyGUI::KeyCode::Add;
|
||||||
|
keyMap[SDLK_KP_1] = MyGUI::KeyCode::Numpad1;
|
||||||
|
keyMap[SDLK_KP_2] = MyGUI::KeyCode::Numpad2;
|
||||||
|
keyMap[SDLK_KP_3] = MyGUI::KeyCode::Numpad3;
|
||||||
|
keyMap[SDLK_KP_0] = MyGUI::KeyCode::Numpad0;
|
||||||
|
keyMap[SDLK_KP_PERIOD] = MyGUI::KeyCode::Decimal;
|
||||||
|
keyMap[SDLK_F11] = MyGUI::KeyCode::F11;
|
||||||
|
keyMap[SDLK_F12] = MyGUI::KeyCode::F12;
|
||||||
|
keyMap[SDLK_F13] = MyGUI::KeyCode::F13;
|
||||||
|
keyMap[SDLK_F14] = MyGUI::KeyCode::F14;
|
||||||
|
keyMap[SDLK_F15] = MyGUI::KeyCode::F15;
|
||||||
|
keyMap[SDLK_KP_EQUALS] = MyGUI::KeyCode::NumpadEquals;
|
||||||
|
keyMap[SDLK_COLON] = MyGUI::KeyCode::Colon;
|
||||||
|
keyMap[SDLK_KP_ENTER] = MyGUI::KeyCode::NumpadEnter;
|
||||||
|
keyMap[SDLK_KP_DIVIDE] = MyGUI::KeyCode::Divide;
|
||||||
|
keyMap[SDLK_SYSREQ] = MyGUI::KeyCode::SysRq;
|
||||||
|
keyMap[SDLK_RALT] = MyGUI::KeyCode::RightAlt;
|
||||||
|
keyMap[SDLK_HOME] = MyGUI::KeyCode::Home;
|
||||||
|
keyMap[SDLK_UP] = MyGUI::KeyCode::ArrowUp;
|
||||||
|
keyMap[SDLK_PAGEUP] = MyGUI::KeyCode::PageUp;
|
||||||
|
keyMap[SDLK_LEFT] = MyGUI::KeyCode::ArrowLeft;
|
||||||
|
keyMap[SDLK_RIGHT] = MyGUI::KeyCode::ArrowRight;
|
||||||
|
keyMap[SDLK_END] = MyGUI::KeyCode::End;
|
||||||
|
keyMap[SDLK_DOWN] = MyGUI::KeyCode::ArrowDown;
|
||||||
|
keyMap[SDLK_PAGEDOWN] = MyGUI::KeyCode::PageDown;
|
||||||
|
keyMap[SDLK_INSERT] = MyGUI::KeyCode::Insert;
|
||||||
|
keyMap[SDLK_DELETE] = MyGUI::KeyCode::Delete;
|
||||||
|
keyMap[SDLK_APPLICATION] = MyGUI::KeyCode::AppMenu;
|
||||||
|
|
||||||
|
//The function of the Ctrl and Meta keys are switched on macOS compared to other platforms.
|
||||||
|
//For instance] = Cmd+C versus Ctrl+C to copy from the system clipboard
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
keyMap[SDLK_LGUI] = MyGUI::KeyCode::LeftControl;
|
||||||
|
keyMap[SDLK_RGUI] = MyGUI::KeyCode::RightControl;
|
||||||
|
keyMap[SDLK_LCTRL] = MyGUI::KeyCode::LeftWindows;
|
||||||
|
keyMap[SDLK_RCTRL] = MyGUI::KeyCode::RightWindows;
|
||||||
|
#else
|
||||||
|
keyMap[SDLK_LGUI] = MyGUI::KeyCode::LeftWindows;
|
||||||
|
keyMap[SDLK_RGUI] = MyGUI::KeyCode::RightWindows;
|
||||||
|
keyMap[SDLK_LCTRL] = MyGUI::KeyCode::LeftControl;
|
||||||
|
keyMap[SDLK_RCTRL] = MyGUI::KeyCode::RightControl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::KeyCode sdlKeyToMyGUI(SDL_Keycode code)
|
||||||
|
{
|
||||||
|
static std::map<SDL_Keycode, MyGUI::KeyCode> keyMap;
|
||||||
|
if (keyMap.empty())
|
||||||
|
initKeyMap(keyMap);
|
||||||
|
|
||||||
|
MyGUI::KeyCode kc = MyGUI::KeyCode::None;
|
||||||
|
auto foundKey = keyMap.find(code);
|
||||||
|
if (foundKey != keyMap.end())
|
||||||
|
kc = foundKey->second;
|
||||||
|
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
}
|
25
apps/openmw/mwinput/sdlmappings.hpp
Normal file
25
apps/openmw/mwinput/sdlmappings.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef MWINPUT_SDLMAPPINGS_H
|
||||||
|
#define MWINPUT_SDLMAPPINGS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <MyGUI_KeyCode.h>
|
||||||
|
|
||||||
|
#include <SDL_keycode.h>
|
||||||
|
|
||||||
|
namespace MyGUI
|
||||||
|
{
|
||||||
|
struct MouseButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
std::string sdlControllerButtonToString(int button);
|
||||||
|
|
||||||
|
std::string sdlControllerAxisToString(int axis);
|
||||||
|
|
||||||
|
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
||||||
|
|
||||||
|
MyGUI::KeyCode sdlKeyToMyGUI(SDL_Keycode code);
|
||||||
|
}
|
||||||
|
#endif
|
267
apps/openmw/mwinput/sensormanager.cpp
Normal file
267
apps/openmw/mwinput/sensormanager.cpp
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
#include "sensormanager.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
SensorManager::SensorManager()
|
||||||
|
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
||||||
|
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
||||||
|
, mGyroXSpeed(0.f)
|
||||||
|
, mGyroYSpeed(0.f)
|
||||||
|
, mGyroUpdateTimer(0.f)
|
||||||
|
, mGyroHSensitivity(Settings::Manager::getFloat("gyro horizontal sensitivity", "Input"))
|
||||||
|
, mGyroVSensitivity(Settings::Manager::getFloat("gyro vertical sensitivity", "Input"))
|
||||||
|
, mGyroHAxis(GyroscopeAxis::Minus_X)
|
||||||
|
, mGyroVAxis(GyroscopeAxis::Y)
|
||||||
|
, mGyroInputThreshold(Settings::Manager::getFloat("gyro input threshold", "Input"))
|
||||||
|
, mGyroscope(nullptr)
|
||||||
|
, mGuiCursorEnabled(true)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::init()
|
||||||
|
{
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
updateSensors();
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorManager::~SensorManager()
|
||||||
|
{
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorManager::GyroscopeAxis SensorManager::mapGyroscopeAxis(const std::string& axis)
|
||||||
|
{
|
||||||
|
if (axis == "x")
|
||||||
|
return GyroscopeAxis::X;
|
||||||
|
else if (axis == "y")
|
||||||
|
return GyroscopeAxis::Y;
|
||||||
|
else if (axis == "z")
|
||||||
|
return GyroscopeAxis::Z;
|
||||||
|
else if (axis == "-x")
|
||||||
|
return GyroscopeAxis::Minus_X;
|
||||||
|
else if (axis == "-y")
|
||||||
|
return GyroscopeAxis::Minus_Y;
|
||||||
|
else if (axis == "-z")
|
||||||
|
return GyroscopeAxis::Minus_Z;
|
||||||
|
|
||||||
|
return GyroscopeAxis::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::correctGyroscopeAxes()
|
||||||
|
{
|
||||||
|
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Treat setting from config as axes for landscape mode.
|
||||||
|
// If the device does not support orientation change, do nothing.
|
||||||
|
// Note: in is unclear how to correct axes for devices with non-standart Z axis direction.
|
||||||
|
mGyroHAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro horizontal axis", "Input"));
|
||||||
|
mGyroVAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro vertical axis", "Input"));
|
||||||
|
|
||||||
|
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::Manager::getInt("screen", "Video"));
|
||||||
|
switch (currentOrientation)
|
||||||
|
{
|
||||||
|
case SDL_ORIENTATION_UNKNOWN:
|
||||||
|
return;
|
||||||
|
case SDL_ORIENTATION_LANDSCAPE:
|
||||||
|
break;
|
||||||
|
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
|
||||||
|
{
|
||||||
|
mGyroHAxis = GyroscopeAxis(-mGyroHAxis);
|
||||||
|
mGyroVAxis = GyroscopeAxis(-mGyroVAxis);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_ORIENTATION_PORTRAIT:
|
||||||
|
{
|
||||||
|
GyroscopeAxis oldVAxis = mGyroVAxis;
|
||||||
|
mGyroVAxis = mGyroHAxis;
|
||||||
|
mGyroHAxis = GyroscopeAxis(-oldVAxis);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
|
||||||
|
{
|
||||||
|
GyroscopeAxis oldVAxis = mGyroVAxis;
|
||||||
|
mGyroVAxis = GyroscopeAxis(-mGyroHAxis);
|
||||||
|
mGyroHAxis = oldVAxis;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::updateSensors()
|
||||||
|
{
|
||||||
|
if (Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
{
|
||||||
|
int numSensors = SDL_NumSensors();
|
||||||
|
for (int i = 0; i < numSensors; ++i)
|
||||||
|
{
|
||||||
|
if (SDL_SensorGetDeviceType(i) == SDL_SENSOR_GYRO)
|
||||||
|
{
|
||||||
|
// It is unclear how to handle several enabled gyroscopes, so use the first one.
|
||||||
|
// Note: Android registers some gyroscope as two separate sensors, for non-wake-up mode and for wake-up mode.
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
mGyroXSpeed = mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: SDL2 does not provide a way to configure a sensor update frequency so far.
|
||||||
|
SDL_Sensor *sensor = SDL_SensorOpen(i);
|
||||||
|
if (sensor == nullptr)
|
||||||
|
Log(Debug::Error) << "Couldn't open sensor " << SDL_SensorGetDeviceName(i) << ": " << SDL_GetError();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mGyroscope = sensor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
mGyroXSpeed = mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
|
{
|
||||||
|
for (const auto& setting : changed)
|
||||||
|
{
|
||||||
|
if (setting.first == "Input" && setting.second == "invert x axis")
|
||||||
|
mInvertX = Settings::Manager::getBool("invert x axis", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "invert y axis")
|
||||||
|
mInvertY = Settings::Manager::getBool("invert y axis", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "gyro horizontal sensitivity")
|
||||||
|
mGyroHSensitivity = Settings::Manager::getFloat("gyro horizontal sensitivity", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "gyro vertical sensitivity")
|
||||||
|
mGyroVSensitivity = Settings::Manager::getFloat("gyro vertical sensitivity", "Input");
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "enable gyroscope")
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "gyro horizontal axis")
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "gyro vertical axis")
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
|
||||||
|
if (setting.first == "Input" && setting.second == "gyro input threshold")
|
||||||
|
mGyroInputThreshold = Settings::Manager::getFloat("gyro input threshold", "Input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float SensorManager::getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const
|
||||||
|
{
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case GyroscopeAxis::X:
|
||||||
|
case GyroscopeAxis::Y:
|
||||||
|
case GyroscopeAxis::Z:
|
||||||
|
return std::abs(arg.data[0]) >= mGyroInputThreshold ? arg.data[axis-1] : 0.f;
|
||||||
|
case GyroscopeAxis::Minus_X:
|
||||||
|
case GyroscopeAxis::Minus_Y:
|
||||||
|
case GyroscopeAxis::Minus_Z:
|
||||||
|
return std::abs(arg.data[0]) >= mGyroInputThreshold ? -arg.data[std::abs(axis)-1] : 0.f;
|
||||||
|
default:
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::displayOrientationChanged()
|
||||||
|
{
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::sensorUpdated(const SDL_SensorEvent &arg)
|
||||||
|
{
|
||||||
|
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_Sensor *sensor = SDL_SensorFromInstanceID(arg.which);
|
||||||
|
if (!sensor)
|
||||||
|
{
|
||||||
|
Log(Debug::Info) << "Couldn't get sensor for sensor event";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (SDL_SensorGetType(sensor))
|
||||||
|
{
|
||||||
|
case SDL_SENSOR_ACCEL:
|
||||||
|
break;
|
||||||
|
case SDL_SENSOR_GYRO:
|
||||||
|
{
|
||||||
|
mGyroXSpeed = getGyroAxisSpeed(mGyroHAxis, arg);
|
||||||
|
mGyroYSpeed = getGyroAxisSpeed(mGyroVAxis, arg);
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::update(float dt)
|
||||||
|
{
|
||||||
|
if (mGyroXSpeed == 0.f && mGyroYSpeed == 0.f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mGyroUpdateTimer > 0.5f)
|
||||||
|
{
|
||||||
|
// More than half of second passed since the last gyroscope update.
|
||||||
|
// A device more likely was disconnected or switched to the sleep mode.
|
||||||
|
// Reset current rotation speed and wait for update.
|
||||||
|
mGyroXSpeed = 0.f;
|
||||||
|
mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGyroUpdateTimer += dt;
|
||||||
|
|
||||||
|
if (!mGuiCursorEnabled)
|
||||||
|
{
|
||||||
|
float rot[3];
|
||||||
|
rot[0] = mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1);
|
||||||
|
rot[1] = 0.0f;
|
||||||
|
rot[2] = mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1);
|
||||||
|
|
||||||
|
// Only actually turn player when we're not in vanity mode
|
||||||
|
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking"))
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.yaw(rot[2]);
|
||||||
|
player.pitch(rot[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
apps/openmw/mwinput/sensormanager.hpp
Normal file
73
apps/openmw/mwinput/sensormanager.hpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef MWINPUT_MWSENSORMANAGER_H
|
||||||
|
#define MWINPUT_MWSENSORMANAGER_H
|
||||||
|
|
||||||
|
#include <SDL_sensor.h>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace SDLUtil
|
||||||
|
{
|
||||||
|
class InputWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class SensorManager : public SDLUtil::SensorListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SensorManager();
|
||||||
|
|
||||||
|
virtual ~SensorManager();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
|
virtual void sensorUpdated(const SDL_SensorEvent &arg);
|
||||||
|
virtual void displayOrientationChanged();
|
||||||
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum GyroscopeAxis
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
X = 1,
|
||||||
|
Y = 2,
|
||||||
|
Z = 3,
|
||||||
|
Minus_X = -1,
|
||||||
|
Minus_Y = -2,
|
||||||
|
Minus_Z = -3
|
||||||
|
};
|
||||||
|
|
||||||
|
void updateSensors();
|
||||||
|
void correctGyroscopeAxes();
|
||||||
|
GyroscopeAxis mapGyroscopeAxis(const std::string& axis);
|
||||||
|
float getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const;
|
||||||
|
|
||||||
|
bool mInvertX;
|
||||||
|
bool mInvertY;
|
||||||
|
|
||||||
|
float mGyroXSpeed;
|
||||||
|
float mGyroYSpeed;
|
||||||
|
float mGyroUpdateTimer;
|
||||||
|
|
||||||
|
float mGyroHSensitivity;
|
||||||
|
float mGyroVSensitivity;
|
||||||
|
GyroscopeAxis mGyroHAxis;
|
||||||
|
GyroscopeAxis mGyroVAxis;
|
||||||
|
float mGyroInputThreshold;
|
||||||
|
|
||||||
|
SDL_Sensor* mGyroscope;
|
||||||
|
|
||||||
|
bool mGuiCursorEnabled;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -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())
|
||||||
|
@ -31,24 +29,35 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool interrupt = false;
|
||||||
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);
|
|
||||||
rebuild = true;
|
rebuild = true;
|
||||||
|
|
||||||
|
// Note: it we expire a Corprus effect, we should remove the whole spell.
|
||||||
|
if (effectIt->mEffectId == ESM::MagicEffect::Corprus)
|
||||||
|
{
|
||||||
|
iter = mSpells.erase (iter);
|
||||||
|
interrupt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectIt = effects.erase(effectIt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
effectIt->mTimeLeft -= duration;
|
||||||
++effectIt;
|
++effectIt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++iter;
|
|
||||||
|
if (!interrupt)
|
||||||
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastUpdate = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSpellsChanged)
|
if (mSpellsChanged)
|
||||||
|
@ -63,24 +72,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 +88,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 +115,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 +146,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 +204,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,6 +290,31 @@ namespace MWMechanics
|
||||||
mSpellsChanged = true;
|
mSpellsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActiveSpells::purgeCorprusDisease()
|
||||||
|
{
|
||||||
|
for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();)
|
||||||
|
{
|
||||||
|
bool hasCorprusEffect = false;
|
||||||
|
for (std::vector<ActiveEffect>::iterator effectIt = iter->second.mEffects.begin();
|
||||||
|
effectIt != iter->second.mEffects.end();++effectIt)
|
||||||
|
{
|
||||||
|
if (effectIt->mEffectId == ESM::MagicEffect::Corprus)
|
||||||
|
{
|
||||||
|
hasCorprusEffect = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCorprusEffect)
|
||||||
|
{
|
||||||
|
mSpells.erase(iter++);
|
||||||
|
mSpellsChanged = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ActiveSpells::clear()
|
void ActiveSpells::clear()
|
||||||
{
|
{
|
||||||
mSpells.clear();
|
mSpells.clear();
|
||||||
|
@ -316,7 +330,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));
|
||||||
}
|
}
|
||||||
|
@ -331,7 +344,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,15 +44,14 @@ 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;
|
||||||
|
|
||||||
/// Add any effects that are in "from" and not in "addTo" to "addTo"
|
/// Add any effects that are in "from" and not in "addTo" to "addTo"
|
||||||
|
@ -100,6 +99,8 @@ namespace MWMechanics
|
||||||
bool isSpellActive (const std::string& id) const;
|
bool isSpellActive (const std::string& id) const;
|
||||||
///< case insensitive
|
///< case insensitive
|
||||||
|
|
||||||
|
void purgeCorprusDisease();
|
||||||
|
|
||||||
const MagicEffects& getMagicEffects() const;
|
const MagicEffects& getMagicEffects() const;
|
||||||
|
|
||||||
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const;
|
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) 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};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "summoning.hpp"
|
#include "summoning.hpp"
|
||||||
#include "combat.hpp"
|
#include "combat.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
#include "tickableeffects.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -111,11 +112,11 @@ void adjustCommandedActor (const MWWorld::Ptr& actor)
|
||||||
|
|
||||||
bool hasCommandPackage = false;
|
bool hasCommandPackage = false;
|
||||||
|
|
||||||
std::list<MWMechanics::AiPackage*>::const_iterator it;
|
auto it = stats.getAiSequence().begin();
|
||||||
for (it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
for (; it != stats.getAiSequence().end(); ++it)
|
||||||
{
|
{
|
||||||
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow &&
|
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow &&
|
||||||
static_cast<MWMechanics::AiFollow*>(*it)->isCommanded())
|
static_cast<const MWMechanics::AiFollow*>(it->get())->isCommanded())
|
||||||
{
|
{
|
||||||
hasCommandPackage = true;
|
hasCommandPackage = true;
|
||||||
break;
|
break;
|
||||||
|
@ -131,7 +132,7 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float
|
||||||
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
|
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
|
||||||
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
float endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
||||||
health = 0.1f * endurance;
|
health = 0.1f * endurance;
|
||||||
|
|
||||||
float fRestMagicMult = settings.find("fRestMagicMult")->mValue.getFloat ();
|
float fRestMagicMult = settings.find("fRestMagicMult")->mValue.getFloat ();
|
||||||
|
@ -175,6 +176,49 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetCurrentMagnitudes : public MWMechanics::EffectSourceVisitor
|
||||||
|
{
|
||||||
|
std::string mSpellId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GetCurrentMagnitudes(const std::string& spellId)
|
||||||
|
: mSpellId(spellId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
|
const std::string& sourceName, const std::string& sourceId, int casterActorId,
|
||||||
|
float magnitude, float remainingTime = -1, float totalTime = -1)
|
||||||
|
{
|
||||||
|
if (magnitude <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sourceId != mSpellId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mMagnitudes.push_back(std::make_pair(key, magnitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<MWMechanics::EffectKey, float>> mMagnitudes;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetCorprusSpells : public MWMechanics::EffectSourceVisitor
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
|
const std::string& sourceName, const std::string& sourceId, int casterActorId,
|
||||||
|
float magnitude, float remainingTime = -1, float totalTime = -1)
|
||||||
|
{
|
||||||
|
if (key.mId != ESM::MagicEffect::Corprus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mSpells.push_back(sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> mSpells;
|
||||||
|
};
|
||||||
|
|
||||||
class SoulTrap : public MWMechanics::EffectSourceVisitor
|
class SoulTrap : public MWMechanics::EffectSourceVisitor
|
||||||
{
|
{
|
||||||
MWWorld::Ptr mCreature;
|
MWWorld::Ptr mCreature;
|
||||||
|
@ -418,7 +462,7 @@ namespace MWMechanics
|
||||||
if (world->isSwimming(actor) || (playerPos - actorPos).length2() >= 3000 * 3000)
|
if (world->isSwimming(actor) || (playerPos - actorPos).length2() >= 3000 * 3000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Our implementation is not FPS-dependent unlike Morrowind's so it needs to be recalibrated.
|
// Our implementation is not FPS-dependent unlike Morrowind's so it needs to be recalibrated.
|
||||||
// We chose to use the chance MW would have when run at 60 FPS with the default value of the GMST.
|
// We chose to use the chance MW would have when run at 60 FPS with the default value of the GMST.
|
||||||
const float delta = MWBase::Environment::get().getFrameDuration() * 6.f;
|
const float delta = MWBase::Environment::get().getFrameDuration() * 6.f;
|
||||||
static const float fVoiceIdleOdds = world->getStore().get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
|
static const float fVoiceIdleOdds = world->getStore().get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
|
||||||
|
@ -434,9 +478,9 @@ namespace MWMechanics
|
||||||
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
||||||
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||||
|
|
||||||
if (!seq.isEmpty() && seq.getActivePackage()->useVariableSpeed())
|
if (!seq.isEmpty() && seq.getActivePackage().useVariableSpeed())
|
||||||
{
|
{
|
||||||
osg::Vec3f targetPos = seq.getActivePackage()->getDestination();
|
osg::Vec3f targetPos = seq.getActivePackage().getDestination();
|
||||||
osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
|
osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
|
||||||
float distance = (targetPos - actorPos).length();
|
float distance = (targetPos - actorPos).length();
|
||||||
if (distance < DECELERATE_DISTANCE)
|
if (distance < DECELERATE_DISTANCE)
|
||||||
|
@ -446,7 +490,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;
|
||||||
|
@ -459,9 +503,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,14 +514,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);
|
||||||
}
|
}
|
||||||
|
@ -492,8 +536,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 &&
|
||||||
|
@ -515,7 +559,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)
|
||||||
{
|
{
|
||||||
|
@ -531,20 +575,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +647,7 @@ namespace MWMechanics
|
||||||
bool isPlayerFollowerOrEscorter = playerAllies.find(actor1) != playerAllies.end();
|
bool isPlayerFollowerOrEscorter = playerAllies.find(actor1) != playerAllies.end();
|
||||||
|
|
||||||
// If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them
|
// If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them
|
||||||
// Doesn't apply for player followers/escorters
|
// Doesn't apply for player followers/escorters
|
||||||
if (!aggressive && !isPlayerFollowerOrEscorter)
|
if (!aggressive && !isPlayerFollowerOrEscorter)
|
||||||
{
|
{
|
||||||
// Check that actor2 is in combat with actor1
|
// Check that actor2 is in combat with actor1
|
||||||
|
@ -673,7 +716,7 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool followerOrEscorter = false;
|
bool followerOrEscorter = false;
|
||||||
for (const AiPackage* package : creatureStats2.getAiSequence())
|
for (const auto& package : creatureStats2.getAiSequence())
|
||||||
{
|
{
|
||||||
// The follow package must be first or have nothing but combat before it
|
// The follow package must be first or have nothing but combat before it
|
||||||
if (package->sideWithTarget())
|
if (package->sideWithTarget())
|
||||||
|
@ -722,7 +765,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr);
|
CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr);
|
||||||
|
|
||||||
int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
float intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||||
|
|
||||||
float base = 1.f;
|
float base = 1.f;
|
||||||
if (ptr == getPlayer())
|
if (ptr == getPlayer())
|
||||||
|
@ -773,6 +816,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)
|
||||||
|
@ -798,7 +844,7 @@ namespace MWMechanics
|
||||||
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
|
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
|
||||||
float fEndFatigueMult = settings.find("fEndFatigueMult")->mValue.getFloat ();
|
float fEndFatigueMult = settings.find("fEndFatigueMult")->mValue.getFloat ();
|
||||||
|
|
||||||
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
float endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
||||||
|
|
||||||
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
|
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
|
||||||
if (normalizedEncumbrance > 1)
|
if (normalizedEncumbrance > 1)
|
||||||
|
@ -825,7 +871,7 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Restore fatigue
|
// Restore fatigue
|
||||||
int endurance = stats.getAttribute(ESM::Attribute::Endurance).getModified();
|
float endurance = stats.getAttribute(ESM::Attribute::Endurance).getModified();
|
||||||
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->mValue.getFloat ();
|
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->mValue.getFloat ();
|
||||||
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
|
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
|
||||||
|
@ -939,20 +985,74 @@ namespace MWMechanics
|
||||||
if (creatureStats.needToRecalcDynamicStats())
|
if (creatureStats.needToRecalcDynamicStats())
|
||||||
calculateDynamicStats(ptr);
|
calculateDynamicStats(ptr);
|
||||||
|
|
||||||
|
if (ptr == getPlayer())
|
||||||
{
|
{
|
||||||
Spells & spells = creatureStats.getSpells();
|
GetCorprusSpells getCorprusSpellsVisitor;
|
||||||
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
creatureStats.getSpells().visitEffectSources(getCorprusSpellsVisitor);
|
||||||
{
|
creatureStats.getActiveSpells().visitEffectSources(getCorprusSpellsVisitor);
|
||||||
if (spells.getCorprusSpells().find(it->first) != spells.getCorprusSpells().end())
|
ptr.getClass().getInventoryStore(ptr).visitEffectSources(getCorprusSpellsVisitor);
|
||||||
{
|
std::vector<std::string> corprusSpells = getCorprusSpellsVisitor.mSpells;
|
||||||
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= spells.getCorprusSpells().at(it->first).mNextWorsening)
|
std::vector<std::string> corprusSpellsToRemove;
|
||||||
{
|
|
||||||
spells.worsenCorprus(it->first);
|
|
||||||
|
|
||||||
if (ptr == getPlayer())
|
for (auto it = creatureStats.getCorprusSpells().begin(); it != creatureStats.getCorprusSpells().end(); ++it)
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}");
|
{
|
||||||
}
|
if(std::find(corprusSpells.begin(), corprusSpells.end(), it->first) == corprusSpells.end())
|
||||||
|
{
|
||||||
|
// Corprus effect expired, remove entry and restore stats.
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->restoreStatsAfterCorprus(ptr, it->first);
|
||||||
|
corprusSpellsToRemove.push_back(it->first);
|
||||||
|
corprusSpells.erase(std::remove(corprusSpells.begin(), corprusSpells.end(), it->first), corprusSpells.end());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
corprusSpells.erase(std::remove(corprusSpells.begin(), corprusSpells.end(), it->first), corprusSpells.end());
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= it->second.mNextWorsening)
|
||||||
|
{
|
||||||
|
it->second.mNextWorsening += CorprusStats::sWorseningPeriod;
|
||||||
|
GetCurrentMagnitudes getMagnitudesVisitor (it->first);
|
||||||
|
creatureStats.getSpells().visitEffectSources(getMagnitudesVisitor);
|
||||||
|
creatureStats.getActiveSpells().visitEffectSources(getMagnitudesVisitor);
|
||||||
|
ptr.getClass().getInventoryStore(ptr).visitEffectSources(getMagnitudesVisitor);
|
||||||
|
for (auto& effectMagnitude : getMagnitudesVisitor.mMagnitudes)
|
||||||
|
{
|
||||||
|
if (effectMagnitude.first.mId == ESM::MagicEffect::FortifyAttribute)
|
||||||
|
{
|
||||||
|
AttributeValue attr = creatureStats.getAttribute(effectMagnitude.first.mArg);
|
||||||
|
attr.damage(-effectMagnitude.second);
|
||||||
|
creatureStats.setAttribute(effectMagnitude.first.mArg, attr);
|
||||||
|
it->second.mWorsenings[effectMagnitude.first.mArg] = 0;
|
||||||
|
}
|
||||||
|
else if (effectMagnitude.first.mId == ESM::MagicEffect::DrainAttribute)
|
||||||
|
{
|
||||||
|
AttributeValue attr = creatureStats.getAttribute(effectMagnitude.first.mArg);
|
||||||
|
int currentDamage = attr.getDamage();
|
||||||
|
if (currentDamage >= 0)
|
||||||
|
it->second.mWorsenings[effectMagnitude.first.mArg] = std::min(it->second.mWorsenings[effectMagnitude.first.mArg], currentDamage);
|
||||||
|
|
||||||
|
it->second.mWorsenings[effectMagnitude.first.mArg] += effectMagnitude.second;
|
||||||
|
attr.damage(effectMagnitude.second);
|
||||||
|
creatureStats.setAttribute(effectMagnitude.first.mArg, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::string& oldCorprusSpell : corprusSpellsToRemove)
|
||||||
|
{
|
||||||
|
creatureStats.removeCorprusSpell(oldCorprusSpell);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::string& newCorprusSpell : corprusSpells)
|
||||||
|
{
|
||||||
|
CorprusStats corprus;
|
||||||
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
|
corprus.mWorsenings[i] = 0;
|
||||||
|
corprus.mNextWorsening = MWBase::Environment::get().getWorld()->getTimeStamp() + CorprusStats::sWorseningPeriod;
|
||||||
|
|
||||||
|
creatureStats.addCorprusSpell(newCorprusSpell, corprus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,11 +1335,6 @@ namespace MWMechanics
|
||||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||||
inventoryStore.unequipItem(*heldIter, ptr);
|
inventoryStore.unequipItem(*heldIter, ptr);
|
||||||
}
|
}
|
||||||
else if (heldIter == inventoryStore.end() || heldIter->getTypeName() == typeid(ESM::Light).name())
|
|
||||||
{
|
|
||||||
// For hostile NPCs, see if they have anything better to equip first
|
|
||||||
inventoryStore.autoEquip(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
|
||||||
|
@ -1623,9 +1718,16 @@ namespace MWMechanics
|
||||||
player.getClass().getCreatureStats(player).setHitAttemptActorId(-1);
|
player.getClass().getCreatureStats(player).setHitAttemptActorId(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For dead actors we need to remove looping spell particles
|
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||||
|
|
||||||
|
// For dead actors we need to update looping spell particles
|
||||||
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||||
|
{
|
||||||
|
// They can be added during the death animation
|
||||||
|
if (!iter->first.getClass().getCreatureStats(iter->first).isDeathAnimationFinished())
|
||||||
|
adjustMagicEffects(iter->first);
|
||||||
ctrl->updateContinuousVfx();
|
ctrl->updateContinuousVfx();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool cellChanged = world->hasCellChanged();
|
bool cellChanged = world->hasCellChanged();
|
||||||
|
@ -1694,7 +1796,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);
|
||||||
}
|
}
|
||||||
|
@ -1738,7 +1840,7 @@ namespace MWMechanics
|
||||||
if (!isPlayer && isConscious(iter->first) && !stats.isParalyzed())
|
if (!isPlayer && isConscious(iter->first) && !stats.isParalyzed())
|
||||||
{
|
{
|
||||||
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||||
alwaysActive = !seq.isEmpty() && seq.getActivePackage()->alwaysActive();
|
alwaysActive = !seq.isEmpty() && seq.getActivePackage().alwaysActive();
|
||||||
}
|
}
|
||||||
bool inRange = isPlayer || dist <= mActorsProcessingRange || alwaysActive;
|
bool inRange = isPlayer || dist <= mActorsProcessingRange || alwaysActive;
|
||||||
int activeFlag = 1; // Can be changed back to '2' to keep updating bounding boxes off screen (more accurate, but slower)
|
int activeFlag = 1; // Can be changed back to '2' to keep updating bounding boxes off screen (more accurate, but slower)
|
||||||
|
@ -1939,12 +2041,18 @@ 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();
|
||||||
|
|
||||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||||
|
|
||||||
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -2154,7 +2262,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat and Wander packages before the Follow/Escort package
|
// An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat and Wander packages before the Follow/Escort package
|
||||||
// Actors that are targeted by this actor's Follow or Escort packages also side with them
|
// Actors that are targeted by this actor's Follow or Escort packages also side with them
|
||||||
for (const AiPackage* package : stats.getAiSequence())
|
for (const auto& package : stats.getAiSequence())
|
||||||
{
|
{
|
||||||
if (package->sideWithTarget() && !package->getTarget().isEmpty())
|
if (package->sideWithTarget() && !package->getTarget().isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -2188,9 +2296,9 @@ namespace MWMechanics
|
||||||
if (stats.isDead())
|
if (stats.isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// An actor counts as following if AiFollow is the current AiPackage,
|
// An actor counts as following if AiFollow is the current AiPackage,
|
||||||
// or there are only Combat and Wander packages before the AiFollow package
|
// or there are only Combat and Wander packages before the AiFollow package
|
||||||
for (const AiPackage* package : stats.getAiSequence())
|
for (const auto& package : stats.getAiSequence())
|
||||||
{
|
{
|
||||||
if (package->followTargetThroughDoors() && package->getTarget() == actor)
|
if (package->followTargetThroughDoors() && package->getTarget() == actor)
|
||||||
list.push_back(iteratedActor);
|
list.push_back(iteratedActor);
|
||||||
|
@ -2253,11 +2361,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
// An actor counts as following if AiFollow is the current AiPackage,
|
// An actor counts as following if AiFollow is the current AiPackage,
|
||||||
// or there are only Combat and Wander packages before the AiFollow package
|
// or there are only Combat and Wander packages before the AiFollow package
|
||||||
for (AiPackage* package : stats.getAiSequence())
|
for (const auto& package : stats.getAiSequence())
|
||||||
{
|
{
|
||||||
if (package->followTargetThroughDoors() && package->getTarget() == actor)
|
if (package->followTargetThroughDoors() && package->getTarget() == actor)
|
||||||
{
|
{
|
||||||
list.push_back(static_cast<AiFollow*>(package)->getFollowIndex());
|
list.push_back(static_cast<const AiFollow*>(package.get())->getFollowIndex());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (package->getTypeId() != AiPackage::TypeIdCombat && package->getTypeId() != AiPackage::TypeIdWander)
|
else if (package->getTypeId() != AiPackage::TypeIdCombat && package->getTypeId() != AiPackage::TypeIdWander)
|
||||||
|
@ -2385,6 +2493,42 @@ namespace MWMechanics
|
||||||
return ctrl->isAttackingOrSpell();
|
return ctrl->isAttackingOrSpell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
@ -194,6 +197,11 @@ namespace MWMechanics
|
||||||
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
||||||
bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const;
|
bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
#ifndef OPENMW_MWMECHANICS_ACTORUTIL_H
|
#ifndef OPENMW_MWMECHANICS_ACTORUTIL_H
|
||||||
#define OPENMW_MWMECHANICS_ACTORUTIL_H
|
#define OPENMW_MWMECHANICS_ACTORUTIL_H
|
||||||
|
|
||||||
|
#include <components/esm/loadcrea.hpp>
|
||||||
|
#include <components/esm/loadnpc.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "./creaturestats.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Ptr;
|
class Ptr;
|
||||||
|
@ -8,9 +18,43 @@ 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);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value)
|
||||||
|
{
|
||||||
|
T copy = *MWBase::Environment::get().getWorld()->getStore().get<T>().find(id);
|
||||||
|
switch(setting)
|
||||||
|
{
|
||||||
|
case MWMechanics::CreatureStats::AiSetting::AI_Hello:
|
||||||
|
copy.mAiData.mHello = value;
|
||||||
|
break;
|
||||||
|
case MWMechanics::CreatureStats::AiSetting::AI_Fight:
|
||||||
|
copy.mAiData.mFight = value;
|
||||||
|
break;
|
||||||
|
case MWMechanics::CreatureStats::AiSetting::AI_Flee:
|
||||||
|
copy.mAiData.mFlee = value;
|
||||||
|
break;
|
||||||
|
case MWMechanics::CreatureStats::AiSetting::AI_Alarm:
|
||||||
|
copy.mAiData.mAlarm = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
MWBase::Environment::get().getWorld()->createOverrideRecord(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
template void setBaseAISetting<ESM::Creature>(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value);
|
||||||
|
template void setBaseAISetting<ESM::NPC>(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,11 +18,6 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AiActivate *MWMechanics::AiActivate::clone() const
|
|
||||||
{
|
|
||||||
return new AiActivate(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AiActivate::execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
bool AiActivate::execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
||||||
{
|
{
|
||||||
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow
|
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow
|
||||||
|
@ -49,11 +44,6 @@ namespace MWMechanics
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiActivate::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdActivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiActivate::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
{
|
{
|
||||||
std::unique_ptr<ESM::AiSequence::AiActivate> activate(new ESM::AiSequence::AiActivate());
|
std::unique_ptr<ESM::AiSequence::AiActivate> activate(new ESM::AiSequence::AiActivate());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_MWMECHANICS_AIACTIVATE_H
|
#ifndef GAME_MWMECHANICS_AIACTIVATE_H
|
||||||
#define GAME_MWMECHANICS_AIACTIVATE_H
|
#define GAME_MWMECHANICS_AIACTIVATE_H
|
||||||
|
|
||||||
#include "aipackage.hpp"
|
#include "typedaipackage.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -19,7 +19,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 TypedAiPackage<AiActivate>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
@ -28,14 +28,14 @@ namespace MWMechanics
|
||||||
|
|
||||||
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
AiActivate(const ESM::AiSequence::AiActivate* activate);
|
||||||
|
|
||||||
virtual AiActivate *clone() const;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
|
||||||
virtual int getTypeId() const;
|
|
||||||
|
|
||||||
virtual void writeState(ESM::AiSequence::AiSequence& sequence) const;
|
static constexpr TypeId getTypeId() { return TypeIdActivate; }
|
||||||
|
|
||||||
|
void writeState(ESM::AiSequence::AiSequence& sequence) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mObjectId;
|
const std::string mObjectId;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // GAME_MWMECHANICS_AIACTIVATE_H
|
#endif // GAME_MWMECHANICS_AIACTIVATE_H
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
static const int MAX_DIRECTIONS = 4;
|
static const int MAX_DIRECTIONS = 4;
|
||||||
|
|
||||||
MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr)
|
MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr)
|
||||||
: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mDirection(0)
|
: mDuration(1), mDoorPtr(doorPtr), mDirection(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,21 +72,6 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiAvoidDoor *MWMechanics::AiAvoidDoor::clone() const
|
|
||||||
{
|
|
||||||
return new AiAvoidDoor(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MWMechanics::AiAvoidDoor::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdAvoidDoor;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiAvoidDoor::getPriority() const
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
||||||
{
|
{
|
||||||
return (actorPos - mLastPos).length2() < 10 * 10;
|
return (actorPos - mLastPos).length2() < 10 * 10;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_MWMECHANICS_AIAVOIDDOOR_H
|
#ifndef GAME_MWMECHANICS_AIAVOIDDOOR_H
|
||||||
#define GAME_MWMECHANICS_AIAVOIDDOOR_H
|
#define GAME_MWMECHANICS_AIAVOIDDOOR_H
|
||||||
|
|
||||||
#include "aipackage.hpp"
|
#include "typedaipackage.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -16,26 +16,28 @@ 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 TypedAiPackage<AiAvoidDoor>
|
||||||
{
|
{
|
||||||
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;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
static constexpr TypeId getTypeId() { return TypeIdAvoidDoor; }
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
virtual unsigned int getPriority() const;
|
AiPackage::Options options;
|
||||||
|
options.mPriority = 2;
|
||||||
virtual bool canCancel() const { return false; }
|
options.mCanCancel = false;
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mDuration;
|
float mDuration;
|
||||||
MWWorld::ConstPtr mDoorPtr;
|
const MWWorld::ConstPtr mDoorPtr;
|
||||||
osg::Vec3f mLastPos;
|
osg::Vec3f mLastPos;
|
||||||
int mDirection;
|
int mDirection;
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,6 @@
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
|
|
||||||
MWMechanics::AiBreathe::AiBreathe()
|
|
||||||
: AiPackage()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
||||||
{
|
{
|
||||||
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->mValue.getFloat();
|
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->mValue.getFloat();
|
||||||
|
@ -37,18 +31,3 @@ bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterContro
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiBreathe *MWMechanics::AiBreathe::clone() const
|
|
||||||
{
|
|
||||||
return new AiBreathe(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MWMechanics::AiBreathe::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdBreathe;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiBreathe::getPriority() const
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
#ifndef GAME_MWMECHANICS_AIBREATHE_H
|
#ifndef GAME_MWMECHANICS_AIBREATHE_H
|
||||||
#define GAME_MWMECHANICS_AIBREATHE_H
|
#define GAME_MWMECHANICS_AIBREATHE_H
|
||||||
|
|
||||||
#include "aipackage.hpp"
|
#include "typedaipackage.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
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 TypedAiPackage<AiBreathe>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AiBreathe();
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual AiBreathe *clone() const;
|
static constexpr TypeId getTypeId() { return TypeIdBreathe; }
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
virtual int getTypeId() const;
|
AiPackage::Options options;
|
||||||
|
options.mPriority = 2;
|
||||||
virtual unsigned int getPriority() const;
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
virtual bool canCancel() const { return false; }
|
return options;
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,22 @@
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
|
|
||||||
MWMechanics::AiCast::AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell)
|
namespace MWMechanics
|
||||||
: mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(0)
|
|
||||||
{
|
{
|
||||||
ActionSpell action = ActionSpell(spellId);
|
namespace
|
||||||
bool isRanged;
|
{
|
||||||
mDistance = action.getCombatRange(isRanged);
|
float getInitialDistance(const std::string& spellId)
|
||||||
|
{
|
||||||
|
ActionSpell action = ActionSpell(spellId);
|
||||||
|
bool isRanged;
|
||||||
|
return action.getCombatRange(isRanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::AiPackage *MWMechanics::AiCast::clone() const
|
MWMechanics::AiCast::AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell)
|
||||||
|
: mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(getInitialDistance(spellId))
|
||||||
{
|
{
|
||||||
return new AiCast(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::CharacterController& characterController, MWMechanics::AiState& state, float duration)
|
bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::CharacterController& characterController, MWMechanics::AiState& state, float duration)
|
||||||
|
@ -84,13 +89,3 @@ MWWorld::Ptr MWMechanics::AiCast::getTarget() const
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::AiCast::getTypeId() const
|
|
||||||
{
|
|
||||||
return AiPackage::TypeIdCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MWMechanics::AiCast::getPriority() const
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_MWMECHANICS_AICAST_H
|
#ifndef GAME_MWMECHANICS_AICAST_H
|
||||||
#define GAME_MWMECHANICS_AICAST_H
|
#define GAME_MWMECHANICS_AICAST_H
|
||||||
|
|
||||||
#include "aipackage.hpp"
|
#include "typedaipackage.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -11,29 +11,31 @@ 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 TypedAiPackage<AiCast> {
|
||||||
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;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
static constexpr TypeId getTypeId() { return TypeIdCast; }
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
MWWorld::Ptr getTarget() const final;
|
||||||
|
|
||||||
virtual MWWorld::Ptr getTarget() const;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
virtual unsigned int getPriority() const;
|
AiPackage::Options options;
|
||||||
|
options.mPriority = 3;
|
||||||
virtual bool canCancel() const { return false; }
|
options.mCanCancel = false;
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mTargetId;
|
const std::string mTargetId;
|
||||||
std::string mSpellId;
|
const std::string mSpellId;
|
||||||
bool mCasting;
|
bool mCasting;
|
||||||
bool mManual;
|
const bool mManual;
|
||||||
float mDistance;
|
const float mDistance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "aicombat.hpp"
|
#include "aicombat.hpp"
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "character.hpp"
|
#include "character.hpp"
|
||||||
#include "aicombataction.hpp"
|
#include "aicombataction.hpp"
|
||||||
#include "coordinateconverter.hpp"
|
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -302,7 +302,7 @@ namespace MWMechanics
|
||||||
if (pathgrid && !actor.getClass().isPureWaterCreature(actor))
|
if (pathgrid && !actor.getClass().isPureWaterCreature(actor))
|
||||||
{
|
{
|
||||||
ESM::Pathgrid::PointList points;
|
ESM::Pathgrid::PointList points;
|
||||||
CoordinateConverter coords(storage.mCell->getCell());
|
Misc::CoordinateConverter coords(storage.mCell->getCell());
|
||||||
|
|
||||||
osg::Vec3f localPos = actor.getRefData().getPosition().asVec3();
|
osg::Vec3f localPos = actor.getRefData().getPosition().asVec3();
|
||||||
coords.toLocal(localPos);
|
coords.toLocal(localPos);
|
||||||
|
@ -406,26 +406,11 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AiCombat::getTypeId() const
|
|
||||||
{
|
|
||||||
return TypeIdCombat;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int AiCombat::getPriority() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::Ptr AiCombat::getTarget() const
|
MWWorld::Ptr AiCombat::getTarget() const
|
||||||
{
|
{
|
||||||
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
AiCombat *MWMechanics::AiCombat::clone() const
|
|
||||||
{
|
|
||||||
return new AiCombat(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiCombat::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiCombat::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
{
|
{
|
||||||
std::unique_ptr<ESM::AiSequence::AiCombat> combat(new ESM::AiSequence::AiCombat());
|
std::unique_ptr<ESM::AiSequence::AiCombat> combat(new ESM::AiSequence::AiCombat());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef GAME_MWMECHANICS_AICOMBAT_H
|
#ifndef GAME_MWMECHANICS_AICOMBAT_H
|
||||||
#define GAME_MWMECHANICS_AICOMBAT_H
|
#define GAME_MWMECHANICS_AICOMBAT_H
|
||||||
|
|
||||||
#include "aipackage.hpp"
|
#include "typedaipackage.hpp"
|
||||||
|
|
||||||
#include "../mwworld/cellstore.hpp" // for Doors
|
#include "../mwworld/cellstore.hpp" // for Doors
|
||||||
|
|
||||||
|
@ -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 TypedAiPackage<AiCombat>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///Constructor
|
///Constructor
|
||||||
|
@ -102,21 +102,23 @@ namespace MWMechanics
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
virtual AiCombat *clone() const;
|
bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final;
|
||||||
|
|
||||||
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
|
static constexpr TypeId getTypeId() { return TypeIdCombat; }
|
||||||
|
|
||||||
virtual int getTypeId() const;
|
static constexpr Options makeDefaultOptions()
|
||||||
|
{
|
||||||
virtual unsigned int getPriority() const;
|
AiPackage::Options options;
|
||||||
|
options.mPriority = 1;
|
||||||
|
options.mCanCancel = false;
|
||||||
|
options.mShouldCancelPreviousAi = false;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
///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; }
|
|
||||||
virtual bool shouldCancelPreviousAi() const { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Returns true if combat should end
|
/// Returns true if combat should end
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
|
||||||
#include "npcstats.hpp"
|
#include "npcstats.hpp"
|
||||||
#include "spellcasting.hpp"
|
|
||||||
#include "combat.hpp"
|
#include "combat.hpp"
|
||||||
#include "weaponpriority.hpp"
|
#include "weaponpriority.hpp"
|
||||||
#include "spellpriority.hpp"
|
#include "spellpriority.hpp"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue