mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-05 16:51:35 +00:00
Add OpenMW commits up to 19 Aug 2018
# Conflicts: # .travis.yml # CI/before_install.linux.sh # CI/before_script.linux.sh # apps/openmw/engine.cpp # apps/openmw/main.cpp # apps/openmw/mwgui/windowmanagerimp.cpp # apps/openmw/mwmechanics/actors.hpp # apps/openmw/mwmechanics/mechanicsmanagerimp.cpp # apps/openmw/mwscript/aiextensions.cpp # apps/openmw/mwscript/containerextensions.cpp # apps/openmw/mwscript/dialogueextensions.cpp # apps/openmw/mwworld/cellstore.cpp # apps/openmw/mwworld/containerstore.cpp # apps/openmw/mwworld/scene.cpp # apps/openmw/mwworld/worldimp.cpp # components/misc/debugging.hpp
This commit is contained in:
commit
84cab59057
158 changed files with 3534 additions and 928 deletions
|
@ -27,8 +27,6 @@ addons:
|
||||||
# Dev
|
# Dev
|
||||||
cmake, clang-6.0, libunshield-dev, libtinyxml-dev,
|
cmake, clang-6.0, libunshield-dev, libtinyxml-dev,
|
||||||
g++-8,
|
g++-8,
|
||||||
# Tests
|
|
||||||
libgtest-dev, google-mock,
|
|
||||||
# Boost
|
# Boost
|
||||||
libboost-filesystem1.61-dev, libboost-program-options1.61-dev, libboost-system1.61-dev,
|
libboost-filesystem1.61-dev, libboost-program-options1.61-dev, libboost-system1.61-dev,
|
||||||
# FFmpeg
|
# FFmpeg
|
||||||
|
|
|
@ -171,7 +171,9 @@ Programmers
|
||||||
viadanna
|
viadanna
|
||||||
Vincent Heuken
|
Vincent Heuken
|
||||||
vocollapse
|
vocollapse
|
||||||
|
Yohaulticetl
|
||||||
zelurker
|
zelurker
|
||||||
|
James Carty (MrTopCat)
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
@ -180,9 +182,11 @@ Documentation
|
||||||
Alejandro Sanchez (HiPhish)
|
Alejandro Sanchez (HiPhish)
|
||||||
Bodillium
|
Bodillium
|
||||||
Bret Curtis (psi29a)
|
Bret Curtis (psi29a)
|
||||||
|
David Walley (Loriel)
|
||||||
Cramal
|
Cramal
|
||||||
Ryan Tucker (Ravenwing)
|
Ryan Tucker (Ravenwing)
|
||||||
sir_herrbatka
|
sir_herrbatka
|
||||||
|
Diego Crespo
|
||||||
|
|
||||||
Packagers
|
Packagers
|
||||||
---------
|
---------
|
||||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -14,14 +14,19 @@
|
||||||
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
||||||
Bug #2872: Tab completion in console doesn't work with explicit reference
|
Bug #2872: Tab completion in console doesn't work with explicit reference
|
||||||
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
||||||
|
Bug #3049: Drain and Fortify effects are not properly applied on health, magicka and fatigue
|
||||||
|
Bug #3072: Fatal error on AddItem <item> that has a script containing Equip <item>
|
||||||
Bug #3249: Fixed revert function not updating views properly
|
Bug #3249: Fixed revert function not updating views properly
|
||||||
Bug #3374: Touch spells not hitting kwama foragers
|
Bug #3374: Touch spells not hitting kwama foragers
|
||||||
Bug #3486: [Mod] NPC Commands does not work
|
Bug #3486: [Mod] NPC Commands does not work
|
||||||
|
Bug #3533: GetSpellEffects should detect effects with zero duration
|
||||||
Bug #3591: Angled hit distance too low
|
Bug #3591: Angled hit distance too low
|
||||||
Bug #3629: DB assassin attack never triggers creature spawning
|
Bug #3629: DB assassin attack never triggers creature spawning
|
||||||
|
Bug #3788: GetPCInJail and GetPCTraveling do not work as in vanilla
|
||||||
Bug #3876: Landscape texture painting is misaligned
|
Bug #3876: Landscape texture painting is misaligned
|
||||||
Bug #3897: Have Goodbye give all choices the effects of Goodbye
|
Bug #3897: Have Goodbye give all choices the effects of Goodbye
|
||||||
Bug #3911: [macOS] Typing in the "Content List name" dialog box produces double characters
|
Bug #3911: [macOS] Typing in the "Content List name" dialog box produces double characters
|
||||||
|
Bug #3948: AiCombat moving target aiming uses incorrect speed for magic projectiles
|
||||||
Bug #3950: FLATTEN_STATIC_TRANSFORMS optimization breaks animated collision shapes
|
Bug #3950: FLATTEN_STATIC_TRANSFORMS optimization breaks animated collision shapes
|
||||||
Bug #3993: Terrain texture blending map is not upscaled
|
Bug #3993: Terrain texture blending map is not upscaled
|
||||||
Bug #3997: Almalexia doesn't pace
|
Bug #3997: Almalexia doesn't pace
|
||||||
|
@ -32,11 +37,14 @@
|
||||||
Bug #4215: OpenMW shows book text after last EOL tag
|
Bug #4215: OpenMW shows book text after last EOL tag
|
||||||
Bug #4221: Characters get stuck in V-shaped terrain
|
Bug #4221: Characters get stuck in V-shaped terrain
|
||||||
Bug #4230: AiTravel package issues break some Tribunal quests
|
Bug #4230: AiTravel package issues break some Tribunal quests
|
||||||
|
Bug #4231: Infected rats from the "Crimson Plague" quest rendered unconscious by change in Drain Fatigue functionality
|
||||||
Bug #4251: Stationary NPCs do not return to their position after combat
|
Bug #4251: Stationary NPCs do not return to their position after combat
|
||||||
|
Bug #4271: Scamp flickers when attacking
|
||||||
Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
|
Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
|
||||||
Bug #4286: Scripted animations can be interrupted
|
Bug #4286: Scripted animations can be interrupted
|
||||||
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
||||||
Bug #4293: Faction members are not aware of faction ownerships in barter
|
Bug #4293: Faction members are not aware of faction ownerships in barter
|
||||||
|
Bug #4304: "Follow" not working as a second AI package
|
||||||
Bug #4307: World cleanup should remove dead bodies only if death animation is finished
|
Bug #4307: World cleanup should remove dead bodies only if death animation is finished
|
||||||
Bug #4311: OpenMW does not handle RootCollisionNode correctly
|
Bug #4311: OpenMW does not handle RootCollisionNode correctly
|
||||||
Bug #4327: Missing animations during spell/weapon stance switching
|
Bug #4327: Missing animations during spell/weapon stance switching
|
||||||
|
@ -62,6 +70,7 @@
|
||||||
Bug #4461: "Open" spell from non-player caster isn't a crime
|
Bug #4461: "Open" spell from non-player caster isn't a crime
|
||||||
Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages
|
Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages
|
||||||
Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal
|
Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal
|
||||||
|
Bug #4470: Non-bipedal creatures with Weapon & Shield flag have inconsistent behaviour
|
||||||
Bug #4474: No fallback when getVampireHead fails
|
Bug #4474: No fallback when getVampireHead fails
|
||||||
Bug #4475: Scripted animations should not cause movement
|
Bug #4475: Scripted animations should not cause movement
|
||||||
Bug #4479: "Game" category on Advanced page is getting too long
|
Bug #4479: "Game" category on Advanced page is getting too long
|
||||||
|
@ -75,6 +84,7 @@
|
||||||
Bug #4503: Cast and ExplodeSpell commands increase alteration skill
|
Bug #4503: Cast and ExplodeSpell commands increase alteration skill
|
||||||
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
||||||
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
||||||
|
Bug #4531: Movement does not reset idle animations
|
||||||
Bug #4539: Paper Doll is affected by GUI scaling
|
Bug #4539: Paper Doll is affected by GUI scaling
|
||||||
Bug #4545: Creatures flee from werewolves
|
Bug #4545: Creatures flee from werewolves
|
||||||
Bug #4551: Replace 0 sound range with default range separately
|
Bug #4551: Replace 0 sound range with default range separately
|
||||||
|
@ -87,6 +97,8 @@
|
||||||
Bug #4574: Player turning animations are twitchy
|
Bug #4574: Player turning animations are twitchy
|
||||||
Bug #4575: Weird result of attack animation blending with movement animations
|
Bug #4575: Weird result of attack animation blending with movement animations
|
||||||
Bug #4576: Reset of idle animations when attack can not be started
|
Bug #4576: Reset of idle animations when attack can not be started
|
||||||
|
Bug #4591: Attack strength should be 0 if player did not hold the attack button
|
||||||
|
Feature #1645: Casting effects from objects
|
||||||
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
||||||
Feature #3083: Play animation when NPC is casting spell via script
|
Feature #3083: Play animation when NPC is casting spell via script
|
||||||
Feature #3103: Provide option for disposition to get increased by successful trade
|
Feature #3103: Provide option for disposition to get increased by successful trade
|
||||||
|
@ -107,6 +119,8 @@
|
||||||
Feature #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill
|
Feature #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill
|
||||||
Feature #4549: Weapon priority: use the actual damage in weapon rating calculations
|
Feature #4549: Weapon priority: use the actual damage in weapon rating calculations
|
||||||
Feature #4550: Weapon priority: make ranged weapon bonus more sensible
|
Feature #4550: Weapon priority: make ranged weapon bonus more sensible
|
||||||
|
Feature #4579: Add option for applying Strength into hand to hand damage
|
||||||
|
Feature #4581: Use proper logging system
|
||||||
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
||||||
Task #4545: Enable is_pod string test
|
Task #4545: Enable is_pod string test
|
||||||
|
|
||||||
|
|
4
CI/before_install.linux.sh
Executable file → Normal file
4
CI/before_install.linux.sh
Executable file → Normal file
|
@ -1,4 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
sudo ln -s /usr/bin/clang-3.6 /usr/local/bin/clang
|
||||||
|
sudo ln -s /usr/bin/clang++-3.6 /usr/local/bin/clang++
|
||||||
|
|
||||||
echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
|
echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
|
||||||
|
|
||||||
# Set up compilers
|
# Set up compilers
|
||||||
|
@ -19,4 +22,3 @@ git clone https://github.com/TES3MP/CrabNet
|
||||||
cd CrabNet
|
cd CrabNet
|
||||||
cmake . -DCRABNET_ENABLE_DLL=OFF -DCRABNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
|
cmake . -DCRABNET_ENABLE_DLL=OFF -DCRABNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
|
||||||
make -j3
|
make -j3
|
||||||
|
|
||||||
|
|
10
CI/before_script.linux.sh
Executable file → Normal file
10
CI/before_script.linux.sh
Executable file → Normal file
|
@ -1,6 +1,10 @@
|
||||||
#!/bin/sh
|
#!/bin/sh -e
|
||||||
|
|
||||||
free -m
|
free -m
|
||||||
|
|
||||||
|
env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh
|
||||||
|
GOOGLETEST_DIR="$(pwd)/googletest/build"
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
|
@ -17,11 +21,11 @@ if [ ! -z "${ANALYZE}" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${ANALYZE}cmake .. \
|
${ANALYZE}cmake .. \
|
||||||
|
-DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} \
|
||||||
-DDESIRED_QT_VERSION=5 \
|
-DDESIRED_QT_VERSION=5 \
|
||||||
-DBUILD_OPENMW_MP=ON \
|
-DBUILD_OPENMW_MP=ON \
|
||||||
-DBUILD_BROWSER=ON \
|
-DBUILD_BROWSER=ON \
|
||||||
-DBUILD_MASTER=ON \
|
-DBUILD_MASTER=ON \
|
||||||
-DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} \
|
|
||||||
-DBUILD_BSATOOL=OFF \
|
-DBUILD_BSATOOL=OFF \
|
||||||
-DBUILD_ESMTOOL=OFF \
|
-DBUILD_ESMTOOL=OFF \
|
||||||
-DBUILD_ESSIMPORTER=OFF \
|
-DBUILD_ESSIMPORTER=OFF \
|
||||||
|
@ -35,5 +39,7 @@ ${ANALYZE}cmake .. \
|
||||||
-DBINDIR=/usr/games \
|
-DBINDIR=/usr/games \
|
||||||
-DCMAKE_BUILD_TYPE="None" \
|
-DCMAKE_BUILD_TYPE="None" \
|
||||||
-DUSE_SYSTEM_TINYXML=TRUE \
|
-DUSE_SYSTEM_TINYXML=TRUE \
|
||||||
|
-DGTEST_ROOT="${GOOGLETEST_DIR}" \
|
||||||
|
-DGMOCK_ROOT="${GOOGLETEST_DIR}" \
|
||||||
-DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a \
|
-DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a \
|
||||||
-DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a
|
-DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a
|
||||||
|
|
13
CI/build_googletest.sh
Executable file
13
CI/build_googletest.sh
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
git clone https://github.com/google/googletest.git
|
||||||
|
cd googletest
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake \
|
||||||
|
-D CMAKE_BUILD_TYPE="${CONFIGURATION}" \
|
||||||
|
-D CMAKE_INSTALL_PREFIX=. \
|
||||||
|
-G "${GENERATOR}" \
|
||||||
|
..
|
||||||
|
cmake --build . --config "${CONFIGURATION}"
|
||||||
|
cmake --build . --target install --config "${CONFIGURATION}"
|
|
@ -1,6 +1,7 @@
|
||||||
set(LAUNCHER
|
set(LAUNCHER
|
||||||
datafilespage.cpp
|
datafilespage.cpp
|
||||||
graphicspage.cpp
|
graphicspage.cpp
|
||||||
|
sdlinit.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
maindialog.cpp
|
maindialog.cpp
|
||||||
playpage.cpp
|
playpage.cpp
|
||||||
|
@ -19,6 +20,7 @@ set(LAUNCHER
|
||||||
set(LAUNCHER_HEADER
|
set(LAUNCHER_HEADER
|
||||||
datafilespage.hpp
|
datafilespage.hpp
|
||||||
graphicspage.hpp
|
graphicspage.hpp
|
||||||
|
sdlinit.hpp
|
||||||
maindialog.hpp
|
maindialog.hpp
|
||||||
playpage.hpp
|
playpage.hpp
|
||||||
textslotmsgbox.hpp
|
textslotmsgbox.hpp
|
||||||
|
|
|
@ -76,6 +76,9 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
|
int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game");
|
||||||
|
if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2)
|
||||||
|
unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex);
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
|
@ -131,6 +134,9 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
|
int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex();
|
||||||
|
if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game"))
|
||||||
|
mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex);
|
||||||
|
|
||||||
// Input Settings
|
// Input Settings
|
||||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
@ -48,27 +47,15 @@ Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, Settings:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher::GraphicsPage::connectToSdl() {
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
|
||||||
SDL_SetMainReady();
|
|
||||||
// Required for determining screen resolution and such on the Graphics tab
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
|
||||||
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Launcher::GraphicsPage::setupSDL()
|
bool Launcher::GraphicsPage::setupSDL()
|
||||||
{
|
{
|
||||||
bool sdlConnectSuccessful = connectToSdl();
|
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||||
|
bool sdlConnectSuccessful = initSDL();
|
||||||
if (!sdlConnectSuccessful)
|
if (!sdlConnectSuccessful)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int displays = SDL_GetNumVideoDisplays();
|
int displays = SDL_GetNumVideoDisplays();
|
||||||
|
|
||||||
|
@ -89,8 +76,10 @@ bool Launcher::GraphicsPage::setupSDL()
|
||||||
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||||
// Disconnect from SDL processes
|
// Disconnect from SDL processes
|
||||||
SDL_Quit();
|
quitSDL();
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
#include "sdlinit.hpp"
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
|
@ -37,11 +39,6 @@ namespace Launcher
|
||||||
QStringList getAvailableResolutions(int screen);
|
QStringList getAvailableResolutions(int screen);
|
||||||
QRect getMaximumResolution();
|
QRect getMaximumResolution();
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to the SDL so that we can use it to determine graphics
|
|
||||||
* @return whether or not connecting to SDL is successful
|
|
||||||
*/
|
|
||||||
bool connectToSdl();
|
|
||||||
bool setupSDL();
|
bool setupSDL();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,18 @@
|
||||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
|
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
#include "sdlinit.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Note: we should init SDL2 before Qt4 to avoid crashes on Linux,
|
||||||
|
// but we should init SDL2 after Qt5 to avoid input issues on MacOS X.
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||||
|
initSDL();
|
||||||
|
#endif
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
// Now we make sure the current dir is set to application path
|
// Now we make sure the current dir is set to application path
|
||||||
|
@ -33,11 +40,18 @@ int main(int argc, char *argv[])
|
||||||
if (result == Launcher::FirstRunDialogResultContinue)
|
if (result == Launcher::FirstRunDialogResultContinue)
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
|
|
||||||
return app.exec();
|
int exitCode = app.exec();
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||||
|
// Disconnect from SDL processes
|
||||||
|
quitSDL();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
apps/launcher/sdlinit.cpp
Normal file
25
apps/launcher/sdlinit.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_video.h>
|
||||||
|
|
||||||
|
bool initSDL()
|
||||||
|
{
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||||
|
SDL_SetMainReady();
|
||||||
|
// Required for determining screen resolution and such on the Graphics tab
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
||||||
|
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void quitSDL()
|
||||||
|
{
|
||||||
|
// Disconnect from SDL processes
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
8
apps/launcher/sdlinit.hpp
Normal file
8
apps/launcher/sdlinit.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef SDLINIT_H
|
||||||
|
#define SDLINIT_H
|
||||||
|
|
||||||
|
bool initSDL();
|
||||||
|
|
||||||
|
void quitSDL();
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,11 +5,8 @@
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/crashcatcher/crashcatcher.hpp>
|
|
||||||
|
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
|
||||||
#include "model/doc/document.hpp"
|
#include "model/doc/document.hpp"
|
||||||
|
@ -27,10 +24,6 @@ CS::Editor::Editor (int argc, char **argv)
|
||||||
mLock(), mMerge (mDocumentManager),
|
mLock(), mMerge (mDocumentManager),
|
||||||
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||||
{
|
{
|
||||||
// install the crash handler as soon as possible. note that the log path
|
|
||||||
// does not depend on config being read.
|
|
||||||
crashCatcherInstall(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string());
|
|
||||||
|
|
||||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||||
|
|
||||||
setupDataFiles (config.first);
|
setupDataFiles (config.first);
|
||||||
|
@ -301,7 +294,7 @@ bool CS::Editor::makeIPCServer()
|
||||||
mLock = boost::interprocess::file_lock(mPid.string().c_str());
|
mLock = boost::interprocess::file_lock(mPid.string().c_str());
|
||||||
if(!mLock.try_lock())
|
if(!mLock.try_lock())
|
||||||
{
|
{
|
||||||
std::cerr << "OpenCS already running." << std::endl;
|
Log(Debug::Error) << "Error: OpenMW-CS is already running.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,17 +317,17 @@ bool CS::Editor::makeIPCServer()
|
||||||
if(boost::filesystem::exists(fullPath.toUtf8().constData()))
|
if(boost::filesystem::exists(fullPath.toUtf8().constData()))
|
||||||
{
|
{
|
||||||
// TODO: compare pid of the current process with that in the file
|
// TODO: compare pid of the current process with that in the file
|
||||||
std::cout << "Detected unclean shutdown." << std::endl;
|
Log(Debug::Info) << "Detected unclean shutdown.";
|
||||||
// delete the stale file
|
// delete the stale file
|
||||||
if(remove(fullPath.toUtf8().constData()))
|
if(remove(fullPath.toUtf8().constData()))
|
||||||
std::cerr << "ERROR removing stale connection file" << std::endl;
|
Log(Debug::Error) << "Error: can not remove stale connection file.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch(const std::exception& e)
|
catch(const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR " << e.what() << std::endl;
|
Log(Debug::Error) << "Error: " << e.what();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#include "editor.hpp"
|
#include "editor.hpp"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
#include <components/misc/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
|
|
||||||
#include "model/doc/messages.hpp"
|
#include "model/doc/messages.hpp"
|
||||||
#include "model/world/universalid.hpp"
|
#include "model/world/universalid.hpp"
|
||||||
|
@ -31,7 +30,7 @@ class Application : public QApplication
|
||||||
}
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
std::cerr << "An exception has been caught: " << exception.what() << std::endl;
|
Log(Debug::Error) << "An exception has been caught: " << exception.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,5 +79,5 @@ int runApplication(int argc, char *argv[])
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
return wrapApplication(&runApplication, argc, argv, "/openmw-cs.log");
|
return wrapApplication(&runApplication, argc, argv, "OpenMW-CS");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
@ -13,6 +12,8 @@
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
void CSMDoc::Document::addGmsts()
|
void CSMDoc::Document::addGmsts()
|
||||||
{
|
{
|
||||||
for (size_t i=0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
|
for (size_t i=0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
|
||||||
|
@ -435,7 +436,7 @@ void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
||||||
{
|
{
|
||||||
/// \todo find a better way to get these messages to the user.
|
/// \todo find a better way to get these messages to the user.
|
||||||
std::cout << message.mMessage << std::endl;
|
Log(Debug::Info) << message.mMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone2 (int type, bool failed)
|
void CSMDoc::Document::operationDone2 (int type, bool failed)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "refcollection.hpp"
|
#include "refcollection.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
||||||
// message
|
// message
|
||||||
if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1])
|
if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1])
|
||||||
{
|
{
|
||||||
std::cerr << "The Position of moved ref "
|
Log(Debug::Warning) << "Warning: the Position of moved ref "
|
||||||
<< ref.mRefID << " does not match the target cell" << std::endl;
|
<< ref.mRefID << " does not match the target cell";
|
||||||
std::cerr << "Position: #" << index.first << " " << index.second
|
Log(Debug::Warning) << "Position: #" << index.first << " " << index.second
|
||||||
<<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl;
|
<<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1];
|
||||||
|
|
||||||
stream.clear();
|
stream.clear();
|
||||||
stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1];
|
stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1];
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <osg/Depth>
|
#include <osg/Depth>
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
@ -24,6 +23,7 @@
|
||||||
#include "../../model/world/cellcoordinates.hpp"
|
#include "../../model/world/cellcoordinates.hpp"
|
||||||
#include "../../model/prefs/state.hpp"
|
#include "../../model/prefs/state.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/sceneutil/lightutil.hpp>
|
#include <components/sceneutil/lightutil.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
@ -133,7 +133,7 @@ void CSVRender::Object::update()
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
// TODO: use error marker mesh
|
// TODO: use error marker mesh
|
||||||
std::cerr << e.what() << std::endl;
|
Log(Debug::Error) << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
@ -73,7 +75,7 @@ namespace
|
||||||
void checkSDLError(int ret)
|
void checkSDLError(int ret)
|
||||||
{
|
{
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
|
Log(Debug::Error) << "SDL error: " << SDL_GetError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +282,7 @@ bool OMW::Engine::frame(float frametime)
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error in frame: " << e.what() << std::endl;
|
Log(Debug::Error) << "Error in frame: " << e.what();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +487,7 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
|
||||||
// Try with a lower AA
|
// Try with a lower AA
|
||||||
if (antialiasing > 0)
|
if (antialiasing > 0)
|
||||||
{
|
{
|
||||||
std::cout << "Note: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2 << std::endl;
|
Log(Debug::Warning) << "Warning: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2;
|
||||||
antialiasing /= 2;
|
antialiasing /= 2;
|
||||||
Settings::Manager::setInt("antialiasing", "Video", antialiasing);
|
Settings::Manager::setInt("antialiasing", "Video", antialiasing);
|
||||||
checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing));
|
checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing));
|
||||||
|
@ -494,7 +496,7 @@ void OMW::Engine::createWindow(Settings::Manager& settings)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
error << "Failed to create SDL window: " << SDL_GetError() << std::endl;
|
error << "Failed to create SDL window: " << SDL_GetError();
|
||||||
throw std::runtime_error(error.str());
|
throw std::runtime_error(error.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,16 +543,16 @@ void OMW::Engine::setWindowIcon()
|
||||||
std::string windowIcon = (mResDir / "mygui" / "openmw.png").string();
|
std::string windowIcon = (mResDir / "mygui" / "openmw.png").string();
|
||||||
windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary);
|
windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary);
|
||||||
if (windowIconStream.fail())
|
if (windowIconStream.fail())
|
||||||
std::cerr << "Error: Failed to open " << windowIcon << std::endl;
|
Log(Debug::Error) << "Error: Failed to open " << windowIcon;
|
||||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||||
if (!reader)
|
if (!reader)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Failed to read window icon, no png readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Failed to read window icon, no png readerwriter found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream);
|
osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
std::cerr << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Image> image = result.getImage();
|
osg::ref_ptr<osg::Image> image = result.getImage();
|
||||||
|
@ -685,21 +687,19 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
{
|
{
|
||||||
std::pair<int, int> result = mEnvironment.getScriptManager()->compileAll();
|
std::pair<int, int> result = mEnvironment.getScriptManager()->compileAll();
|
||||||
if (result.first)
|
if (result.first)
|
||||||
std::cout
|
Log(Debug::Info)
|
||||||
<< "compiled " << result.second << " of " << result.first << " scripts ("
|
<< "compiled " << result.second << " of " << result.first << " scripts ("
|
||||||
<< 100*static_cast<double> (result.second)/result.first
|
<< 100*static_cast<double> (result.second)/result.first
|
||||||
<< "%)"
|
<< "%)";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
if (mCompileAllDialogue)
|
if (mCompileAllDialogue)
|
||||||
{
|
{
|
||||||
std::pair<int, int> result = MWDialogue::ScriptTest::compileAll(&mExtensions, mWarningsMode);
|
std::pair<int, int> result = MWDialogue::ScriptTest::compileAll(&mExtensions, mWarningsMode);
|
||||||
if (result.first)
|
if (result.first)
|
||||||
std::cout
|
Log(Debug::Info)
|
||||||
<< "compiled " << result.second << " of " << result.first << " dialogue script/actor combinations a("
|
<< "compiled " << result.second << " of " << result.first << " dialogue script/actor combinations a("
|
||||||
<< 100*static_cast<double> (result.second)/result.first
|
<< 100*static_cast<double> (result.second)/result.first
|
||||||
<< "%)"
|
<< "%)";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,14 +735,14 @@ public:
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension(mScreenshotFormat);
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension(mScreenshotFormat);
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't write screenshot, no '" << mScreenshotFormat << "' readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Can't write screenshot, no '" << mScreenshotFormat << "' readerwriter found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(image, outStream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(image, outStream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't write screenshot: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Can't write screenshot: " << result.message() << " code " << result.status();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,7 +768,7 @@ void OMW::Engine::go()
|
||||||
End of tes3mp change (major)
|
End of tes3mp change (major)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::cout << "OSG version: " << osgGetVersion() << std::endl;
|
Log(Debug::Info) << "OSG version: " << osgGetVersion();
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
Settings::Manager settings;
|
Settings::Manager settings;
|
||||||
|
@ -902,7 +902,7 @@ void OMW::Engine::go()
|
||||||
// Save user settings
|
// Save user settings
|
||||||
settings.saveUser(settingspath);
|
settings.saveUser(settingspath);
|
||||||
|
|
||||||
std::cout << "Quitting peacefully." << std::endl;
|
Log(Debug::Info) << "Quitting peacefully.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::setCompileAll (bool all)
|
void OMW::Engine::setCompileAll (bool all)
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <components/version/version.hpp>
|
#include <components/version/version.hpp>
|
||||||
#include <components/crashcatcher/crashcatcher.hpp>
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/escape.hpp>
|
#include <components/files/escape.hpp>
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
#include <components/misc/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
@ -284,8 +281,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
StringsVector content = variables["content"].as<Files::EscapeStringVector>().toStdStringVector();
|
StringsVector content = variables["content"].as<Files::EscapeStringVector>().toStdStringVector();
|
||||||
if (content.empty())
|
if (content.empty())
|
||||||
{
|
{
|
||||||
std::cout << "No content file given (esm/esp, nor omwgame/omwaddon). Aborting..." << std::endl;
|
Log(Debug::Error) << "No content file given (esm/esp, nor omwgame/omwaddon). Aborting...";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringsVector::const_iterator it(content.begin());
|
StringsVector::const_iterator it(content.begin());
|
||||||
|
@ -299,7 +296,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
engine.setCell(variables["start"].as<Files::EscapeHashString>().toStdString());
|
engine.setCell(variables["start"].as<Files::EscapeHashString>().toStdString());
|
||||||
engine.setSkipMenu (variables["skip-menu"].as<bool>(), variables["new-game"].as<bool>());
|
engine.setSkipMenu (variables["skip-menu"].as<bool>(), variables["new-game"].as<bool>());
|
||||||
if (!variables["skip-menu"].as<bool>() && variables["new-game"].as<bool>())
|
if (!variables["skip-menu"].as<bool>() && variables["new-game"].as<bool>())
|
||||||
std::cerr << "Warning: new-game used without skip-menu -> ignoring it" << std::endl;
|
Log(Debug::Warning) << "Warning: new-game used without skip-menu -> ignoring it";
|
||||||
|
|
||||||
// scripts
|
// scripts
|
||||||
engine.setCompileAll(variables["script-all"].as<bool>());
|
engine.setCompileAll(variables["script-all"].as<bool>());
|
||||||
|
@ -356,13 +353,23 @@ extern "C" int SDL_main(int argc, char**argv)
|
||||||
int main(int argc, char**argv)
|
int main(int argc, char**argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Initialize the logger added for multiplayer
|
||||||
|
*/
|
||||||
|
LOG_INIT(TimedLog::LOG_INFO);
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
Instead of logging information in openmw.log, use a more descriptive filename
|
Instead of logging information in openmw.log, use a more descriptive filename
|
||||||
that includes a timestamp
|
that includes a timestamp
|
||||||
*/
|
*/
|
||||||
return wrapApplication(&runApplication, argc, argv, "/tes3mp-client-" + TimedLog::getFilenameTimestamp() + ".log");
|
return wrapApplication(&runApplication, argc, argv, "/tes3mp-client-" + TimedLog::getFilenameTimestamp());
|
||||||
/*
|
/*
|
||||||
End of tes3mp change (major)
|
End of tes3mp change (major)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -278,7 +278,7 @@ namespace MWBase
|
||||||
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
||||||
virtual bool isAttackPrepairing(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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -708,7 +708,7 @@ namespace MWBase
|
||||||
/// Spawn a blood effect for \a ptr at \a worldPosition
|
/// Spawn a blood effect for \a ptr at \a worldPosition
|
||||||
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
|
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
|
||||||
|
|
||||||
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0;
|
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) = 0;
|
||||||
|
|
||||||
virtual void explodeSpell(const osg::Vec3f& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster,
|
virtual void explodeSpell(const osg::Vec3f& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster,
|
||||||
const MWWorld::Ptr& ignore, ESM::RangeType rangeType, const std::string& id,
|
const MWWorld::Ptr& ignore, ESM::RangeType rangeType, const std::string& id,
|
||||||
|
@ -738,6 +738,9 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool isPlayerInJail() const = 0;
|
virtual bool isPlayerInJail() const = 0;
|
||||||
|
|
||||||
|
virtual void setPlayerTraveling(bool traveling) = 0;
|
||||||
|
virtual bool isPlayerTraveling() const = 0;
|
||||||
|
|
||||||
virtual void rotateWorldObject (const MWWorld::Ptr& ptr, osg::Quat rotate) = 0;
|
virtual void rotateWorldObject (const MWWorld::Ptr& ptr, osg::Quat rotate) = 0;
|
||||||
|
|
||||||
/// Return terrain height at \a worldPos position.
|
/// Return terrain height at \a worldPos position.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "creature.hpp"
|
#include "creature.hpp"
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
#include <components/esm/creaturestate.hpp>
|
#include <components/esm/creaturestate.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
@ -161,7 +161,7 @@ namespace MWClass
|
||||||
if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(*iter))
|
if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(*iter))
|
||||||
data->mCreatureStats.getSpells().add (spell);
|
data->mCreatureStats.getSpells().add (spell);
|
||||||
else /// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility
|
else /// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility
|
||||||
std::cerr << "Warning: ignoring nonexistent spell '" << *iter << "' on creature '" << ref->mBase->mId << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: ignoring nonexistent spell '" << *iter << "' on creature '" << ref->mBase->mId << "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
// inventory
|
// inventory
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/loadmgef.hpp>
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
#include <components/esm/npcstate.hpp>
|
#include <components/esm/npcstate.hpp>
|
||||||
|
@ -380,7 +381,7 @@ namespace MWClass
|
||||||
if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(*iter))
|
if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(*iter))
|
||||||
data->mNpcStats.getSpells().add (spell);
|
data->mNpcStats.getSpells().add (spell);
|
||||||
else
|
else
|
||||||
std::cerr << "Warning: ignoring nonexistent race power '" << *iter << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: ignoring nonexistent race power '" << *iter << "' on NPC '" << ref->mBase->mId << "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ref->mBase->mFaction.empty())
|
if (!ref->mBase->mFaction.empty())
|
||||||
|
@ -410,7 +411,7 @@ namespace MWClass
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility
|
/// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility
|
||||||
std::cerr << "Warning: ignoring nonexistent spell '" << *iter << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: ignoring nonexistent spell '" << *iter << "' on NPC '" << ref->mBase->mId << "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/loaddial.hpp>
|
#include <components/esm/loaddial.hpp>
|
||||||
#include <components/esm/loadinfo.hpp>
|
#include <components/esm/loadinfo.hpp>
|
||||||
|
@ -240,16 +241,14 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
catch (const std::exception& error)
|
catch (const std::exception& error)
|
||||||
{
|
{
|
||||||
std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what() << std::endl;
|
Log(Debug::Error) << std::string ("Dialogue error: An exception has been thrown: ") + error.what();
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "Warning: compiling failed (dialogue script)" << std::endl
|
<< "Warning: compiling failed (dialogue script)\n" << cmd << "\n\n";
|
||||||
<< cmd
|
|
||||||
<< std::endl << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -282,7 +281,7 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
catch (const std::exception& error)
|
catch (const std::exception& error)
|
||||||
{
|
{
|
||||||
std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what() << std::endl;
|
Log(Debug::Error) << std::string ("Dialogue error: An exception has been thrown: ") + error.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "scripttest.hpp"
|
#include "scripttest.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -12,6 +10,7 @@
|
||||||
|
|
||||||
#include "../mwscript/compilercontext.hpp"
|
#include "../mwscript/compilercontext.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/compiler/exception.hpp>
|
#include <components/compiler/exception.hpp>
|
||||||
#include <components/compiler/streamerrorhandler.hpp>
|
#include <components/compiler/streamerrorhandler.hpp>
|
||||||
#include <components/compiler/scanner.hpp>
|
#include <components/compiler/scanner.hpp>
|
||||||
|
@ -80,16 +79,14 @@ void test(const MWWorld::Ptr& actor, int &compiled, int &total, const Compiler::
|
||||||
}
|
}
|
||||||
catch (const std::exception& error)
|
catch (const std::exception& error)
|
||||||
{
|
{
|
||||||
std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what() << std::endl;
|
Log(Debug::Error) << std::string ("Dialogue error: An exception has been thrown: ") + error.what();
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "compiling failed (dialogue script)" << std::endl
|
<< "compiling failed (dialogue script)\n" << info->mResultScript << "\n\n";
|
||||||
<< info->mResultScript
|
|
||||||
<< std::endl << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "charactercreation.hpp"
|
#include "charactercreation.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -284,7 +285,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Failed to create chargen window: " << e.what() << std::endl;
|
Log(Debug::Error) << "Error: Failed to create chargen window: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +615,7 @@ namespace MWGui
|
||||||
mGenerateClass = "Mage";
|
mGenerateClass = "Mage";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Failed to deduce class from chosen answers in generate class dialog" << std::endl;
|
Log(Debug::Warning) << "Failed to deduce class from chosen answers in generate class dialog.";
|
||||||
mGenerateClass = "Thief";
|
mGenerateClass = "Thief";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include "tooltips.hpp"
|
#include "tooltips.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -924,7 +926,7 @@ namespace MWGui
|
||||||
std::string classImage = std::string("textures\\levelup\\") + classId + ".dds";
|
std::string classImage = std::string("textures\\levelup\\") + classId + ".dds";
|
||||||
if (!MWBase::Environment::get().getWindowManager()->textureExists(classImage))
|
if (!MWBase::Environment::get().getWindowManager()->textureExists(classImage))
|
||||||
{
|
{
|
||||||
std::cout << "No class image for " << classId << ", falling back to default" << std::endl;
|
Log(Debug::Warning) << "No class image for " << classId << ", falling back to default";
|
||||||
classImage = "textures\\levelup\\warrior.dds";
|
classImage = "textures\\levelup\\warrior.dds";
|
||||||
}
|
}
|
||||||
imageBox->setImageTexture(classImage);
|
imageBox->setImageTexture(classImage);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <MyGUI_ScrollBar.h>
|
#include <MyGUI_ScrollBar.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/widgets/list.hpp>
|
#include <components/widgets/list.hpp>
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
|
|
||||||
|
@ -411,7 +412,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (!actor.getClass().isActor())
|
if (!actor.getClass().isActor())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: can not talk with non-actor object." << std::endl;
|
Log(Debug::Warning) << "Warning: can not talk with non-actor object.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/interpreter/defines.hpp>
|
#include <components/interpreter/defines.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
@ -300,7 +301,7 @@ namespace MWGui
|
||||||
|
|
||||||
if (!exists)
|
if (!exists)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Could not find \"" << src << "\" referenced by an <img> tag." << std::endl;
|
Log(Debug::Warning) << "Warning: Could not find \"" << src << "\" referenced by an <img> tag.";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -531,7 +531,7 @@ namespace MWGui
|
||||||
|
|
||||||
// Give the script a chance to run once before we do anything else
|
// Give the script a chance to run once before we do anything else
|
||||||
// this is important when setting pcskipequip as a reaction to onpcequip being set (bk_treasuryreport does this)
|
// this is important when setting pcskipequip as a reaction to onpcequip being set (bk_treasuryreport does this)
|
||||||
if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
|
if (!force && !script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
|
||||||
{
|
{
|
||||||
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
|
||||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
#include <MyGUI_TextBox.h>
|
#include <MyGUI_TextBox.h>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#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>
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ namespace MWGui
|
||||||
++found;
|
++found;
|
||||||
}
|
}
|
||||||
if (mSplashScreens.empty())
|
if (mSplashScreens.empty())
|
||||||
std::cerr << "No splash screens found!" << std::endl;
|
Log(Debug::Warning) << "Warning: no splash screens found!";
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadingScreen::setLabel(const std::string &label, bool important)
|
void LoadingScreen::setLabel(const std::string &label, bool important)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <MyGUI_RenderManager.h>
|
#include <MyGUI_RenderManager.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -125,7 +126,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (mInterMessageBoxe != NULL)
|
if (mInterMessageBoxe != NULL)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: replacing an interactive message box that was not answered yet" << std::endl;
|
Log(Debug::Warning) << "Warning: replacing an interactive message box that was not answered yet";
|
||||||
mInterMessageBoxe->setVisible(false);
|
mInterMessageBoxe->setVisible(false);
|
||||||
delete mInterMessageBoxe;
|
delete mInterMessageBoxe;
|
||||||
mInterMessageBoxe = NULL;
|
mInterMessageBoxe = NULL;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/myguiplatform/myguitexture.hpp>
|
#include <components/myguiplatform/myguitexture.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
@ -351,7 +352,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error creating preview: " << e.what() << std::endl;
|
Log(Debug::Error) << "Error creating preview: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/myguiplatform/myguitexture.hpp>
|
#include <components/myguiplatform/myguitexture.hpp>
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -438,14 +440,14 @@ namespace MWGui
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't open savegame screenshot, no jpg readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Can't open savegame screenshot, no jpg readerwriter found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(instream);
|
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(instream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Failed to read savegame screenshot: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Failed to read savegame screenshot: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/widgets/sharedstatebutton.hpp>
|
#include <components/widgets/sharedstatebutton.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
@ -31,7 +32,8 @@ namespace
|
||||||
if (val == "linear") return "Trilinear";
|
if (val == "linear") return "Trilinear";
|
||||||
if (val == "nearest") return "Bilinear";
|
if (val == "nearest") return "Bilinear";
|
||||||
if (val != "none")
|
if (val != "none")
|
||||||
std::cerr<< "Warning: Invalid texture mipmap option: "<<val <<std::endl;
|
Log(Debug::Warning) << "Warning: Invalid texture mipmap option: "<< val;
|
||||||
|
|
||||||
return "Other";
|
return "Other";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +415,7 @@ namespace MWGui
|
||||||
else if(pos == 1)
|
else if(pos == 1)
|
||||||
Settings::Manager::setString("texture mipmap", "General", "linear");
|
Settings::Manager::setString("texture mipmap", "General", "linear");
|
||||||
else
|
else
|
||||||
std::cerr<< "Unexpected option pos "<<pos <<std::endl;
|
Log(Debug::Warning) << "Unexpected option pos " << pos;
|
||||||
apply();
|
apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#include "sortfilteritemmodel.hpp"
|
#include "sortfilteritemmodel.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/loadalch.hpp>
|
#include <components/esm/loadalch.hpp>
|
||||||
#include <components/esm/loadappa.hpp>
|
#include <components/esm/loadappa.hpp>
|
||||||
#include <components/esm/loadarmo.hpp>
|
#include <components/esm/loadarmo.hpp>
|
||||||
|
@ -245,7 +243,7 @@ namespace MWGui
|
||||||
const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().search(enchId);
|
const ESM::Enchantment* ench = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().search(enchId);
|
||||||
if (!ench)
|
if (!ench)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Can't find enchantment '" << enchId << "' on item " << base.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: Can't find enchantment '" << enchId << "' on item " << base.getCellRef().getRefId();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "spellmodel.hpp"
|
#include "spellmodel.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -94,7 +94,7 @@ namespace MWGui
|
||||||
const ESM::Enchantment* enchant = esmStore.get<ESM::Enchantment>().search(enchantId);
|
const ESM::Enchantment* enchant = esmStore.get<ESM::Enchantment>().search(enchantId);
|
||||||
if (!enchant)
|
if (!enchant)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Can't find enchantment '" << enchantId << "' on item " << item.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: Can't find enchantment '" << enchantId << "' on item " << item.getCellRef().getRefId();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,10 @@ namespace MWGui
|
||||||
if (playerGold<price)
|
if (playerGold<price)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Set "traveling" flag, so GetPCTraveling can detect teleportation.
|
||||||
|
// We will reset this flag during next world update.
|
||||||
|
MWBase::Environment::get().getWorld()->setPlayerTraveling(true);
|
||||||
|
|
||||||
if (!mPtr.getCell()->isExterior())
|
if (!mPtr.getCell()->isExterior())
|
||||||
// Interior cell -> mages guild transport
|
// Interior cell -> mages guild transport
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("mysticism cast");
|
MWBase::Environment::get().getWindowManager()->playSound("mysticism cast");
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/myguiplatform/myguitexture.hpp>
|
#include <components/myguiplatform/myguitexture.hpp>
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ void VideoWidget::playVideo(const std::string &video)
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open video: " << e.what() << std::endl;
|
Log(Debug::Error) << "Failed to open video: " << e.what();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/sdlutil/sdlcursormanager.hpp>
|
#include <components/sdlutil/sdlcursormanager.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
@ -1153,7 +1155,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (!mStore)
|
if (!mStore)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '" << tag << "'" << std::endl;
|
Log(Debug::Error) << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '" << tag << "'";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ESM::GameSetting *setting = mStore->get<ESM::GameSetting>().find(tag);
|
const ESM::GameSetting *setting = mStore->get<ESM::GameSetting>().find(tag);
|
||||||
|
@ -1917,7 +1919,7 @@ namespace MWGui
|
||||||
if (found != mCurrentModals.end())
|
if (found != mCurrentModals.end())
|
||||||
mCurrentModals.erase(found);
|
mCurrentModals.erase(found);
|
||||||
else
|
else
|
||||||
std::cerr << " warning: can't find modal window " << input << std::endl;
|
Log(Debug::Warning) << "Warning: can't find modal window " << input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mCurrentModals.empty())
|
if (mCurrentModals.empty())
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <SDL_version.h>
|
#include <SDL_version.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/sdlutil/sdlinputwrapper.hpp>
|
#include <components/sdlutil/sdlinputwrapper.hpp>
|
||||||
#include <components/sdlutil/sdlvideowrapper.hpp>
|
#include <components/sdlutil/sdlvideowrapper.hpp>
|
||||||
|
|
||||||
|
@ -132,11 +133,11 @@ namespace MWInput
|
||||||
SDL_ControllerDeviceEvent evt;
|
SDL_ControllerDeviceEvent evt;
|
||||||
evt.which = i;
|
evt.which = i;
|
||||||
controllerAdded(mFakeDeviceID, evt);
|
controllerAdded(mFakeDeviceID, evt);
|
||||||
std::cout << "Detected game controller: " << SDL_GameControllerNameForIndex(i) << std::endl;
|
Log(Debug::Info) << "Detected game controller: " << SDL_GameControllerNameForIndex(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Detected unusable controller: " << SDL_JoystickNameForIndex(i) << std::endl;
|
Log(Debug::Info) << "Detected unusable controller: " << SDL_JoystickNameForIndex(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,9 +1041,9 @@ namespace MWInput
|
||||||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We want to interrupt animation only if attack is prepairing, but still is not triggered
|
// 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
|
// Otherwise we will get a "speedshooting" exploit, when player can skip reload animation by hitting "Toggle Weapon" key twice
|
||||||
if (MWBase::Environment::get().getMechanicsManager()->isAttackPrepairing(mPlayer->getPlayer()))
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackPreparing(mPlayer->getPlayer()))
|
||||||
mPlayer->setAttackingOrSpell(false);
|
mPlayer->setAttackingOrSpell(false);
|
||||||
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -445,7 +444,7 @@ namespace MWMechanics
|
||||||
std::set<MWWorld::Ptr> playerAllies;
|
std::set<MWWorld::Ptr> playerAllies;
|
||||||
getActorsSidingWith(MWMechanics::getPlayer(), playerAllies, cachedAllies);
|
getActorsSidingWith(MWMechanics::getPlayer(), playerAllies, cachedAllies);
|
||||||
|
|
||||||
bool isPlayerFollowerOrEscorter = std::find(playerAllies.begin(), playerAllies.end(), 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
|
||||||
|
@ -499,7 +498,7 @@ namespace MWMechanics
|
||||||
// Do aggression check if actor2 is the player or a player follower or escorter
|
// Do aggression check if actor2 is the player or a player follower or escorter
|
||||||
if (!aggressive)
|
if (!aggressive)
|
||||||
{
|
{
|
||||||
if (againstPlayer || std::find(playerAllies.begin(), playerAllies.end(), actor2) != playerAllies.end())
|
if (againstPlayer || playerAllies.find(actor2) != playerAllies.end())
|
||||||
{
|
{
|
||||||
// Player followers and escorters with high fight should not initiate combat with the player or with
|
// Player followers and escorters with high fight should not initiate combat with the player or with
|
||||||
// other player followers or escorters
|
// other player followers or escorters
|
||||||
|
@ -599,7 +598,7 @@ namespace MWMechanics
|
||||||
float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase();
|
float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase();
|
||||||
float currentToBaseRatio = (magicka.getCurrent() / magicka.getBase());
|
float currentToBaseRatio = (magicka.getCurrent() / magicka.getBase());
|
||||||
magicka.setModified(magicka.getModified() + diff, 0);
|
magicka.setModified(magicka.getModified() + diff, 0);
|
||||||
magicka.setCurrent(magicka.getBase() * currentToBaseRatio);
|
magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true);
|
||||||
creatureStats.setMagicka(magicka);
|
creatureStats.setMagicka(magicka);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,8 +629,14 @@ namespace MWMechanics
|
||||||
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
|
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
|
||||||
if (normalizedEncumbrance > 1)
|
if (normalizedEncumbrance > 1)
|
||||||
normalizedEncumbrance = 1;
|
normalizedEncumbrance = 1;
|
||||||
|
|
||||||
|
// Current fatigue can be above base value due to a fortify effect.
|
||||||
|
// In that case stop here and don't try to restore.
|
||||||
|
DynamicStat<float> fatigue = stats.getFatigue();
|
||||||
|
if (fatigue.getCurrent() >= fatigue.getBase())
|
||||||
|
return;
|
||||||
|
|
||||||
// restore fatigue
|
// Restore fatigue
|
||||||
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
|
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
|
||||||
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
|
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
|
||||||
float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat ();
|
float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat ();
|
||||||
|
@ -639,7 +644,6 @@ namespace MWMechanics
|
||||||
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
|
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
|
||||||
x *= fEndFatigueMult * endurance;
|
x *= fEndFatigueMult * endurance;
|
||||||
|
|
||||||
DynamicStat<float> fatigue = stats.getFatigue();
|
|
||||||
fatigue.setCurrent (fatigue.getCurrent() + 3600 * x);
|
fatigue.setCurrent (fatigue.getCurrent() + 3600 * x);
|
||||||
stats.setFatigue (fatigue);
|
stats.setFatigue (fatigue);
|
||||||
}
|
}
|
||||||
|
@ -651,16 +655,20 @@ namespace MWMechanics
|
||||||
|
|
||||||
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
|
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
|
||||||
|
|
||||||
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
|
// Current fatigue can be above base value due to a fortify effect.
|
||||||
|
// In that case stop here and don't try to restore.
|
||||||
|
DynamicStat<float> fatigue = stats.getFatigue();
|
||||||
|
if (fatigue.getCurrent() >= fatigue.getBase())
|
||||||
|
return;
|
||||||
|
|
||||||
// restore fatigue
|
// Restore fatigue
|
||||||
|
int 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")->getFloat ();
|
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
|
||||||
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
|
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
|
||||||
|
|
||||||
float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
|
float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
|
||||||
|
|
||||||
DynamicStat<float> fatigue = stats.getFatigue();
|
|
||||||
fatigue.setCurrent (fatigue.getCurrent() + duration * x);
|
fatigue.setCurrent (fatigue.getCurrent() + duration * x);
|
||||||
stats.setFatigue (fatigue);
|
stats.setFatigue (fatigue);
|
||||||
}
|
}
|
||||||
|
@ -741,6 +749,19 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamic stats
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
||||||
|
stat.setCurrentModifier(effects.get(ESM::MagicEffect::FortifyHealth + i).getMagnitude() -
|
||||||
|
effects.get(ESM::MagicEffect::DrainHealth + i).getMagnitude(),
|
||||||
|
// Magicka can be decreased below zero due to a fortify effect wearing off
|
||||||
|
// Fatigue can be decreased below zero meaning the actor will be knocked out
|
||||||
|
i == 1 || i == 2);
|
||||||
|
|
||||||
|
creatureStats.setDynamic(i, stat);
|
||||||
|
}
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
for(int i = 0;i < ESM::Attribute::Length;++i)
|
for(int i = 0;i < ESM::Attribute::Length;++i)
|
||||||
{
|
{
|
||||||
|
@ -772,19 +793,6 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dynamic stats
|
|
||||||
for(int i = 0;i < 3;++i)
|
|
||||||
{
|
|
||||||
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
|
||||||
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).getMagnitude() -
|
|
||||||
effects.get(ESM::MagicEffect::DrainHealth+i).getMagnitude(),
|
|
||||||
// Magicka can be decreased below zero due to a fortify effect wearing off
|
|
||||||
// Fatigue can be decreased below zero meaning the actor will be knocked out
|
|
||||||
i == 1 || i == 2);
|
|
||||||
|
|
||||||
creatureStats.setDynamic(i, stat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AI setting modifiers
|
// AI setting modifiers
|
||||||
int creature = !ptr.getClass().isNpc();
|
int creature = !ptr.getClass().isNpc();
|
||||||
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Humanoid)
|
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Humanoid)
|
||||||
|
@ -960,14 +968,14 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Actors::isAttackPrepairing(const MWWorld::Ptr& ptr)
|
bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
PtrActorMap::iterator it = mActors.find(ptr);
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
if (it == mActors.end())
|
if (it == mActors.end())
|
||||||
return false;
|
return false;
|
||||||
CharacterController* ctrl = it->second->getCharacterController();
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
return ctrl->isAttackPrepairing();
|
return ctrl->isAttackPreparing();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
@ -1975,7 +1983,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr<< "Warning: Actors::playAnimationGroup: Unable to find " << ptr.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: Actors::playAnimationGroup: Unable to find " << ptr.getCellRef().getRefId();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2023,38 +2031,35 @@ namespace MWMechanics
|
||||||
std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor)
|
std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
std::list<MWWorld::Ptr> list;
|
std::list<MWWorld::Ptr> list;
|
||||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = iter->first.getClass();
|
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||||
const CreatureStats &stats = cls.getCreatureStats(iter->first);
|
if (iteratedActor == getPlayer())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||||
if (stats.isDead())
|
if (stats.isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat 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
|
||||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
|
||||||
{
|
|
||||||
if ((*it)->sideWithTarget() && (*it)->getTarget() == actor)
|
|
||||||
{
|
|
||||||
list.push_back(iter->first);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 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
|
||||||
if (actor != getPlayer())
|
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||||
{
|
{
|
||||||
const CreatureStats &stats2 = actor.getClass().getCreatureStats(actor);
|
const MWWorld::Ptr &target = (*package)->getTarget();
|
||||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it2 = stats2.getAiSequence().begin(); it2 != stats2.getAiSequence().end(); ++it2)
|
if ((*package)->sideWithTarget() && !target.isEmpty())
|
||||||
{
|
{
|
||||||
if ((*it2)->sideWithTarget() && !(*it2)->getTarget().isEmpty())
|
if (iteratedActor == actor)
|
||||||
{
|
{
|
||||||
list.push_back((*it2)->getTarget());
|
list.push_back(target);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if ((*it2)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
else if (target == actor)
|
||||||
break;
|
{
|
||||||
|
list.push_back(iteratedActor);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
@ -2065,17 +2070,21 @@ namespace MWMechanics
|
||||||
std::list<MWWorld::Ptr> list;
|
std::list<MWWorld::Ptr> list;
|
||||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = iter->first.getClass();
|
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
if (iteratedActor == getPlayer())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||||
if (stats.isDead())
|
if (stats.isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package
|
// An actor counts as following if AiFollow is the current AiPackage,
|
||||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
// or there are only Combat and Wander packages before the AiFollow package
|
||||||
|
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||||
{
|
{
|
||||||
if ((*it)->followTargetThroughDoors() && (*it)->getTarget() == actor)
|
if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor)
|
||||||
list.push_back(iter->first);
|
list.push_back(iteratedActor);
|
||||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2124,24 +2133,24 @@ namespace MWMechanics
|
||||||
std::list<int> list;
|
std::list<int> list;
|
||||||
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = iter->first.getClass();
|
const MWWorld::Ptr &iteratedActor = iter->first;
|
||||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
if (iteratedActor == getPlayer())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
|
||||||
if (stats.isDead())
|
if (stats.isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package
|
// An actor counts as following if AiFollow is the current AiPackage,
|
||||||
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
|
// or there are only Combat and Wander packages before the AiFollow package
|
||||||
|
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
|
||||||
{
|
{
|
||||||
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow)
|
if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr followTarget = (*it)->getTarget();
|
list.push_back(static_cast<AiFollow*>(*package)->getFollowIndex());
|
||||||
if (followTarget.isEmpty())
|
|
||||||
continue;
|
|
||||||
if (followTarget == actor)
|
|
||||||
list.push_back(static_cast<MWMechanics::AiFollow*>(*it)->getFollowIndex());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2153,14 +2162,14 @@ namespace MWMechanics
|
||||||
std::vector<MWWorld::Ptr> neighbors;
|
std::vector<MWWorld::Ptr> neighbors;
|
||||||
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
||||||
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
||||||
for(std::vector<MWWorld::Ptr>::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter)
|
for(auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = iter->getClass();
|
const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
|
||||||
const CreatureStats &stats = cls.getCreatureStats(*iter);
|
if (stats.isDead() || *neighbor == actor)
|
||||||
if (stats.isDead() || *iter == actor)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (stats.getAiSequence().isInCombat(actor))
|
if (stats.getAiSequence().isInCombat(actor))
|
||||||
list.push_front(*iter);
|
list.push_front(*neighbor);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -2172,15 +2181,18 @@ namespace MWMechanics
|
||||||
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
|
||||||
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
getObjectsInRange(position, aiProcessingDistance, neighbors);
|
||||||
|
|
||||||
std::list<MWWorld::Ptr> followers = getActorsFollowing(actor);
|
std::set<MWWorld::Ptr> followers;
|
||||||
for(std::vector<MWWorld::Ptr>::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter)
|
getActorsFollowing(actor, followers);
|
||||||
|
for (auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor)
|
||||||
{
|
{
|
||||||
const CreatureStats &stats = iter->getClass().getCreatureStats(*iter);
|
const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
|
||||||
if (stats.isDead() || *iter == actor || iter->getClass().isPureWaterCreature(*iter))
|
if (stats.isDead() || *neighbor == actor || neighbor->getClass().isPureWaterCreature(*neighbor))
|
||||||
continue;
|
continue;
|
||||||
const bool isFollower = std::find(followers.begin(), followers.end(), *iter) != followers.end();
|
|
||||||
if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*iter, actor) && !isFollower))
|
const bool isFollower = followers.find(*neighbor) != followers.end();
|
||||||
list.push_back(*iter);
|
|
||||||
|
if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*neighbor, actor) && !isFollower))
|
||||||
|
list.push_back(*neighbor);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ namespace MWMechanics
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool isAttackPrepairing(const MWWorld::Ptr& ptr);
|
bool isAttackPreparing(const MWWorld::Ptr& ptr);
|
||||||
bool isRunning(const MWWorld::Ptr& ptr);
|
bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
bool isSneaking(const MWWorld::Ptr& ptr);
|
bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,19 @@ bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::Charac
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f dir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3();
|
osg::Vec3f targetPos = target.getRefData().getPosition().asVec3();
|
||||||
|
if (target.getClass().isActor())
|
||||||
|
{
|
||||||
|
osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(target);
|
||||||
|
targetPos.z() += halfExtents.z() * 2 * 0.75f;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3();
|
||||||
|
osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
|
||||||
|
actorPos.z() += halfExtents.z() * 2 * 0.75f;
|
||||||
|
|
||||||
|
osg::Vec3f dir = targetPos - actorPos;
|
||||||
|
|
||||||
bool turned = smoothTurn(actor, getZAngleToDir(dir), 2, osg::DegreesToRadians(3.f));
|
bool turned = smoothTurn(actor, getZAngleToDir(dir), 2, osg::DegreesToRadians(3.f));
|
||||||
turned &= smoothTurn(actor, getXAngleToDir(dir), 0, osg::DegreesToRadians(3.f));
|
turned &= smoothTurn(actor, getXAngleToDir(dir), 0, osg::DegreesToRadians(3.f));
|
||||||
|
|
||||||
|
|
|
@ -438,21 +438,32 @@ namespace MWMechanics
|
||||||
actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1];
|
actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1];
|
||||||
actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2];
|
actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2];
|
||||||
|
|
||||||
rotateActorOnAxis(actor, 2, actorMovementSettings, storage.mMovement);
|
rotateActorOnAxis(actor, 2, actorMovementSettings, storage);
|
||||||
rotateActorOnAxis(actor, 0, actorMovementSettings, storage.mMovement);
|
rotateActorOnAxis(actor, 0, actorMovementSettings, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiCombat::rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
void AiCombat::rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
||||||
MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement)
|
MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage)
|
||||||
{
|
{
|
||||||
actorMovementSettings.mRotation[axis] = 0;
|
actorMovementSettings.mRotation[axis] = 0;
|
||||||
float& targetAngleRadians = desiredMovement.mRotation[axis];
|
float& targetAngleRadians = storage.mMovement.mRotation[axis];
|
||||||
if (targetAngleRadians != 0)
|
if (targetAngleRadians != 0)
|
||||||
{
|
{
|
||||||
if (smoothTurn(actor, targetAngleRadians, axis))
|
// Some attack animations contain small amount of movement.
|
||||||
|
// Since we use cone shapes for melee, we can use a threshold to avoid jittering
|
||||||
|
std::shared_ptr<Action>& currentAction = storage.mCurrentAction;
|
||||||
|
bool isRangedCombat = false;
|
||||||
|
currentAction->getCombatRange(isRangedCombat);
|
||||||
|
// Check if the actor now facing desired direction, no need to turn any more
|
||||||
|
if (isRangedCombat)
|
||||||
{
|
{
|
||||||
// actor now facing desired direction, no need to turn any more
|
if (smoothTurn(actor, targetAngleRadians, axis))
|
||||||
targetAngleRadians = 0;
|
targetAngleRadians = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (smoothTurn(actor, targetAngleRadians, axis, osg::DegreesToRadians(3.f)))
|
||||||
|
targetAngleRadians = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,7 +530,7 @@ namespace MWMechanics
|
||||||
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
||||||
{
|
{
|
||||||
mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right
|
mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right
|
||||||
mTimerCombatMove = 0.05f + 0.15f * Misc::Rng::rollClosedProbability();
|
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
|
||||||
mCombatMove = true;
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -684,27 +695,26 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
|
||||||
float duration, int weapType, float strength)
|
float duration, int weapType, float strength)
|
||||||
{
|
{
|
||||||
float projSpeed;
|
float projSpeed;
|
||||||
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
// get projectile speed (depending on weapon type)
|
// get projectile speed (depending on weapon type)
|
||||||
if (weapType == ESM::Weapon::MarksmanThrown)
|
if (weapType == ESM::Weapon::MarksmanThrown)
|
||||||
{
|
{
|
||||||
static float fThrownWeaponMinSpeed =
|
static float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->getFloat();
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fThrownWeaponMinSpeed")->getFloat();
|
static float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->getFloat();
|
||||||
static float fThrownWeaponMaxSpeed =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fThrownWeaponMaxSpeed")->getFloat();
|
|
||||||
|
|
||||||
projSpeed =
|
projSpeed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * strength;
|
||||||
fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * strength;
|
|
||||||
}
|
}
|
||||||
else
|
else if (weapType != 0)
|
||||||
{
|
{
|
||||||
static float fProjectileMinSpeed =
|
static float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->getFloat();
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fProjectileMinSpeed")->getFloat();
|
static float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat();
|
||||||
static float fProjectileMaxSpeed =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fProjectileMaxSpeed")->getFloat();
|
|
||||||
|
|
||||||
projSpeed =
|
projSpeed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * strength;
|
||||||
fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * strength;
|
}
|
||||||
|
else // weapType is 0 ==> it's a target spell projectile
|
||||||
|
{
|
||||||
|
projSpeed = gmst.find("fTargetSpellMaxSpeed")->getFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same
|
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace MWMechanics
|
||||||
/// Transfer desired movement (from AiCombatStorage) to Actor
|
/// Transfer desired movement (from AiCombatStorage) to Actor
|
||||||
void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage);
|
void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage);
|
||||||
void rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
void rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
||||||
MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement);
|
MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "aisequence.hpp"
|
#include "aisequence.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
#include "aicombataction.hpp"
|
#include "aicombataction.hpp"
|
||||||
#include "aipursue.hpp"
|
#include "aipursue.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -122,6 +123,20 @@ bool AiSequence::isInCombat() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AiSequence::isEngagedWithActor() const
|
||||||
|
{
|
||||||
|
for (std::list<AiPackage *>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr target2 = (*it)->getTarget();
|
||||||
|
if (!target2.isEmpty() && target2.getClass().isNpc())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool AiSequence::hasPackage(int typeId) const
|
bool AiSequence::hasPackage(int typeId) const
|
||||||
{
|
{
|
||||||
for (std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
for (std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
|
||||||
|
@ -282,7 +297,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error during AiSequence::execute: " << e.what() << std::endl;
|
Log(Debug::Error) << "Error during AiSequence::execute: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,9 @@ namespace MWMechanics
|
||||||
/// Is there any combat package?
|
/// Is there any combat package?
|
||||||
bool isInCombat () const;
|
bool isInCombat () const;
|
||||||
|
|
||||||
|
/// Are we in combat with any other actor, who's also engaging us?
|
||||||
|
bool isEngagedWithActor () const;
|
||||||
|
|
||||||
/// Does this AI sequence have the given package type?
|
/// Does this AI sequence have the given package type?
|
||||||
bool hasPackage(int typeId) const;
|
bool hasPackage(int typeId) const;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "aiwander.hpp"
|
#include "aiwander.hpp"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -24,8 +23,6 @@
|
||||||
#include "coordinateconverter.hpp"
|
#include "coordinateconverter.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
static const int COUNT_BEFORE_RESET = 10;
|
static const int COUNT_BEFORE_RESET = 10;
|
||||||
|
@ -677,7 +674,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr<< "Error: Attempted to play out of range idle animation \""<<idleSelect<<"\" for " << actor.getCellRef().getRefId() << std::endl;
|
Log(Debug::Verbose) << "Attempted to play out of range idle animation \"" << idleSelect << "\" for " << actor.getCellRef().getRefId();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,10 +427,6 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
|
||||||
if(force || movement != mMovementState)
|
if(force || movement != mMovementState)
|
||||||
{
|
{
|
||||||
mMovementState = movement;
|
mMovementState = movement;
|
||||||
|
|
||||||
if (movement != CharState_None)
|
|
||||||
mIdleState = CharState_None;
|
|
||||||
|
|
||||||
std::string movementAnimName;
|
std::string movementAnimName;
|
||||||
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
|
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
|
||||||
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
|
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
|
||||||
|
@ -547,7 +543,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
|
||||||
|
|
||||||
void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force)
|
void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force)
|
||||||
{
|
{
|
||||||
if(force || idle != mIdleState || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty()))
|
if(force || idle != mIdleState || mIdleState == CharState_None || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty()))
|
||||||
{
|
{
|
||||||
mIdleState = idle;
|
mIdleState = idle;
|
||||||
size_t numLoops = ~0ul;
|
size_t numLoops = ~0ul;
|
||||||
|
@ -578,14 +574,24 @@ void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterStat
|
||||||
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
||||||
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
||||||
numLoops = 1 + Misc::Rng::rollDice(4);
|
numLoops = 1 + Misc::Rng::rollDice(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimation->disable(mCurrentIdle);
|
// There is no need to restart anim if the new and old anims are the same.
|
||||||
|
// Just update a number of loops.
|
||||||
|
float startPoint = 0;
|
||||||
|
if (!mCurrentIdle.empty() && mCurrentIdle == idleGroup)
|
||||||
|
{
|
||||||
|
mAnimation->getInfo(mCurrentIdle, &startPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!mCurrentIdle.empty())
|
||||||
|
mAnimation->disable(mCurrentIdle);
|
||||||
|
|
||||||
mCurrentIdle = idleGroup;
|
mCurrentIdle = idleGroup;
|
||||||
if(!mCurrentIdle.empty())
|
if(!mCurrentIdle.empty())
|
||||||
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
||||||
1.0f, "start", "stop", 0.0f, numLoops, true);
|
1.0f, "start", "stop", startPoint, numLoops, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +605,7 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||||
refreshHitRecoilAnims();
|
refreshHitRecoilAnims();
|
||||||
|
|
||||||
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
|
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
|
||||||
if (!mPtr.getClass().isBipedal(mPtr))
|
if (!mPtr.getClass().hasInventoryStore(mPtr))
|
||||||
weap = sWeaponTypeListEnd;
|
weap = sWeaponTypeListEnd;
|
||||||
|
|
||||||
refreshJumpAnims(weap, jump, force);
|
refreshJumpAnims(weap, jump, force);
|
||||||
|
@ -608,7 +614,7 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||||
// idle handled last as it can depend on the other states
|
// idle handled last as it can depend on the other states
|
||||||
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
|
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
|
||||||
// the idle animation should be displayed
|
// the idle animation should be displayed
|
||||||
if ((mUpperBodyState != UpperCharState_Nothing
|
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|
||||||
|| (mMovementState != CharState_None && !isTurning())
|
|| (mMovementState != CharState_None && !isTurning())
|
||||||
|| mHitState != CharState_None)
|
|| mHitState != CharState_None)
|
||||||
&& !mPtr.getClass().isBipedal(mPtr))
|
&& !mPtr.getClass().isBipedal(mPtr))
|
||||||
|
@ -803,6 +809,20 @@ void CharacterController::playRandomDeath(float startpoint)
|
||||||
playDeath(startpoint, mDeathState);
|
playDeath(startpoint, mDeathState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CharacterController::chooseRandomAttackAnimation() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
bool isSwimming = MWBase::Environment::get().getWorld()->isSwimming(mPtr);
|
||||||
|
|
||||||
|
if (isSwimming)
|
||||||
|
result = chooseRandomGroup("swimattack");
|
||||||
|
|
||||||
|
if (!isSwimming || !mAnimation->hasAnimation(result))
|
||||||
|
result = chooseRandomGroup("attack");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim)
|
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim)
|
||||||
: mPtr(ptr)
|
: mPtr(ptr)
|
||||||
, mWeapon(MWWorld::Ptr())
|
, mWeapon(MWWorld::Ptr())
|
||||||
|
@ -1183,16 +1203,10 @@ bool CharacterController::updateCreatureState()
|
||||||
else
|
else
|
||||||
mCurrentWeapon = "";
|
mCurrentWeapon = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weapType != WeapType_Spell || !mAnimation->hasAnimation("spellcast")) // Not all creatures have a dedicated spellcast animation
|
if (weapType != WeapType_Spell || !mAnimation->hasAnimation("spellcast")) // Not all creatures have a dedicated spellcast animation
|
||||||
{
|
{
|
||||||
bool isSwimming = MWBase::Environment::get().getWorld()->isSwimming(mPtr);
|
mCurrentWeapon = chooseRandomAttackAnimation();
|
||||||
int roll = Misc::Rng::rollDice(3); // [0, 2]
|
|
||||||
if (roll == 0)
|
|
||||||
mCurrentWeapon = isSwimming && mAnimation->hasAnimation("swimattack1") ? "swimattack1" : "attack1";
|
|
||||||
else if (roll == 1)
|
|
||||||
mCurrentWeapon = isSwimming && mAnimation->hasAnimation("swimattack2") ? "swimattack2" : "attack2";
|
|
||||||
else
|
|
||||||
mCurrentWeapon = isSwimming && mAnimation->hasAnimation("swimattack3") ? "swimattack3" : "attack3";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mCurrentWeapon.empty())
|
if (!mCurrentWeapon.empty())
|
||||||
|
@ -1272,9 +1286,10 @@ bool CharacterController::updateWeaponState()
|
||||||
mWeapon = weapon != inv.end() ? *weapon : MWWorld::Ptr();
|
mWeapon = weapon != inv.end() ? *weapon : MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply 1st-person weapon animations only for upper body
|
// Use blending only with 3d-person movement animations for bipedal actors
|
||||||
|
bool firstPersonPlayer = (mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson());
|
||||||
MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon);
|
MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon);
|
||||||
if (mPtr != MWMechanics::getPlayer() || !MWBase::Environment::get().getWorld()->isFirstPerson())
|
if (!firstPersonPlayer && mPtr.getClass().isBipedal(mPtr))
|
||||||
priorityWeapon[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody;
|
priorityWeapon[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody;
|
||||||
|
|
||||||
bool forcestateupdate = false;
|
bool forcestateupdate = false;
|
||||||
|
@ -1301,6 +1316,10 @@ bool CharacterController::updateWeaponState()
|
||||||
MWRender::Animation::BlendMask_All, false,
|
MWRender::Animation::BlendMask_All, false,
|
||||||
1.0f, "unequip start", "unequip stop", 0.0f, 0);
|
1.0f, "unequip start", "unequip stop", 0.0f, 0);
|
||||||
mUpperBodyState = UpperCharState_UnEquipingWeap;
|
mUpperBodyState = UpperCharState_UnEquipingWeap;
|
||||||
|
|
||||||
|
// If we do not have the "unequip detach" key, hide weapon manually.
|
||||||
|
if (mAnimation->getTextKeyTime(weapgroup+": unequip detach") < 0)
|
||||||
|
mAnimation->showWeapons(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!downSoundId.empty())
|
if(!downSoundId.empty())
|
||||||
|
@ -1312,7 +1331,6 @@ bool CharacterController::updateWeaponState()
|
||||||
|
|
||||||
float complete;
|
float complete;
|
||||||
bool animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
bool animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||||
|
|
||||||
if (!animPlaying || complete >= 1.0f)
|
if (!animPlaying || complete >= 1.0f)
|
||||||
{
|
{
|
||||||
// Weapon is changed, no current animation (e.g. unequipping or attack).
|
// Weapon is changed, no current animation (e.g. unequipping or attack).
|
||||||
|
@ -1335,6 +1353,13 @@ bool CharacterController::updateWeaponState()
|
||||||
MWRender::Animation::BlendMask_All, true,
|
MWRender::Animation::BlendMask_All, true,
|
||||||
1.0f, "equip start", "equip stop", 0.0f, 0);
|
1.0f, "equip start", "equip stop", 0.0f, 0);
|
||||||
mUpperBodyState = UpperCharState_EquipingWeap;
|
mUpperBodyState = UpperCharState_EquipingWeap;
|
||||||
|
|
||||||
|
// If we do not have the "equip attach" key, show weapon manually.
|
||||||
|
if (weaptype != WeapType_Spell)
|
||||||
|
{
|
||||||
|
if (mAnimation->getTextKeyTime(weapgroup+": equip attach") < 0)
|
||||||
|
mAnimation->showWeapons(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,6 +1450,7 @@ bool CharacterController::updateWeaponState()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||||
mAttackStrength = 0;
|
mAttackStrength = 0;
|
||||||
|
|
||||||
if(mWeaponType == WeapType_Spell)
|
if(mWeaponType == WeapType_Spell)
|
||||||
{
|
{
|
||||||
// Unset casting flag, otherwise pressing the mouse button down would
|
// Unset casting flag, otherwise pressing the mouse button down would
|
||||||
|
@ -1433,15 +1459,10 @@ bool CharacterController::updateWeaponState()
|
||||||
if (mPtr == player)
|
if (mPtr == player)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setAttackingOrSpell(false);
|
MWBase::Environment::get().getWorld()->getPlayer().setAttackingOrSpell(false);
|
||||||
}
|
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
// For the player, set the spell we want to cast
|
||||||
|
// This has to be done at the start of the casting animation,
|
||||||
// For the player, set the spell we want to cast
|
// *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation)
|
||||||
// This has to be done at the start of the casting animation,
|
|
||||||
// *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation)
|
|
||||||
if (mPtr == player)
|
|
||||||
{
|
|
||||||
std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
||||||
stats.getSpells().setSelectedSpell(selectedSpell);
|
stats.getSpells().setSelectedSpell(selectedSpell);
|
||||||
}
|
}
|
||||||
|
@ -1472,6 +1493,7 @@ bool CharacterController::updateWeaponState()
|
||||||
MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell);
|
MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell);
|
||||||
cast.playSpellCastingEffects(spellid);
|
cast.playSpellCastingEffects(spellid);
|
||||||
|
|
||||||
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
||||||
const ESM::MagicEffect *effect;
|
const ESM::MagicEffect *effect;
|
||||||
|
@ -1491,16 +1513,31 @@ bool CharacterController::updateWeaponState()
|
||||||
|
|
||||||
const ESM::ENAMstruct &firstEffect = spell->mEffects.mList.at(0); // first effect used for casting animation
|
const ESM::ENAMstruct &firstEffect = spell->mEffects.mList.at(0); // first effect used for casting animation
|
||||||
|
|
||||||
switch(firstEffect.mRange)
|
std::string startKey;
|
||||||
|
std::string stopKey;
|
||||||
|
if (isRandomAttackAnimation(mCurrentWeapon))
|
||||||
{
|
{
|
||||||
case 0: mAttackType = "self"; break;
|
startKey = "start";
|
||||||
case 1: mAttackType = "touch"; break;
|
stopKey = "stop";
|
||||||
case 2: mAttackType = "target"; break;
|
MWBase::Environment::get().getWorld()->castSpell(mPtr, mCastingManualSpell); // No "release" text key to use, so cast immediately
|
||||||
|
mCastingManualSpell = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(firstEffect.mRange)
|
||||||
|
{
|
||||||
|
case 0: mAttackType = "self"; break;
|
||||||
|
case 1: mAttackType = "touch"; break;
|
||||||
|
case 2: mAttackType = "target"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
startKey = mAttackType+" start";
|
||||||
|
stopKey = mAttackType+" stop";
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, priorityWeapon,
|
mAnimation->play(mCurrentWeapon, priorityWeapon,
|
||||||
MWRender::Animation::BlendMask_All, true,
|
MWRender::Animation::BlendMask_All, true,
|
||||||
weapSpeed, mAttackType+" start", mAttackType+" stop",
|
1, startKey, stopKey,
|
||||||
0.0f, 0);
|
0.0f, 0);
|
||||||
mUpperBodyState = UpperCharState_CastingSpell;
|
mUpperBodyState = UpperCharState_CastingSpell;
|
||||||
}
|
}
|
||||||
|
@ -1548,9 +1585,19 @@ bool CharacterController::updateWeaponState()
|
||||||
}
|
}
|
||||||
else if (ammunition)
|
else if (ammunition)
|
||||||
{
|
{
|
||||||
if(mWeaponType == WeapType_Crossbow || mWeaponType == WeapType_BowAndArrow ||
|
std::string startKey;
|
||||||
mWeaponType == WeapType_Thrown)
|
std::string stopKey;
|
||||||
|
if(mWeaponType == WeapType_Crossbow || mWeaponType == WeapType_BowAndArrow || mWeaponType == WeapType_Thrown)
|
||||||
|
{
|
||||||
mAttackType = "shoot";
|
mAttackType = "shoot";
|
||||||
|
startKey = mAttackType+" start";
|
||||||
|
stopKey = mAttackType+" min attack";
|
||||||
|
}
|
||||||
|
else if (isRandomAttackAnimation(mCurrentWeapon))
|
||||||
|
{
|
||||||
|
startKey = "start";
|
||||||
|
stopKey = "stop";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1567,7 +1614,7 @@ bool CharacterController::updateWeaponState()
|
||||||
{
|
{
|
||||||
if (isWeapon)
|
if (isWeapon)
|
||||||
{
|
{
|
||||||
if (Settings::Manager::getBool("best attack", "Game"))
|
if (Settings::Manager::getBool("best attack", "Game"))
|
||||||
{
|
{
|
||||||
MWWorld::ConstContainerStoreIterator weapon = mPtr.getClass().getInventoryStore(mPtr).getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ConstContainerStoreIterator weapon = mPtr.getClass().getInventoryStore(mPtr).getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
mAttackType = getBestAttack(weapon->get<ESM::Weapon>()->mBase);
|
mAttackType = getBestAttack(weapon->get<ESM::Weapon>()->mBase);
|
||||||
|
@ -1576,14 +1623,19 @@ bool CharacterController::updateWeaponState()
|
||||||
setAttackTypeBasedOnMovement();
|
setAttackTypeBasedOnMovement();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
setAttackTypeRandomly(mAttackType);
|
{
|
||||||
|
// There is no "best attack" for Hand-to-Hand
|
||||||
|
setAttackTypeRandomly(mAttackType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// else if (mPtr != getPlayer()) use mAttackType set by AiCombat
|
// else if (mPtr != getPlayer()) use mAttackType set by AiCombat
|
||||||
|
startKey = mAttackType+" start";
|
||||||
|
stopKey = mAttackType+" min attack";
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, priorityWeapon,
|
mAnimation->play(mCurrentWeapon, priorityWeapon,
|
||||||
MWRender::Animation::BlendMask_All, false,
|
MWRender::Animation::BlendMask_All, false,
|
||||||
weapSpeed, mAttackType+" start", mAttackType+" min attack",
|
weapSpeed, startKey, stopKey,
|
||||||
0.0f, 0);
|
0.0f, 0);
|
||||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||||
}
|
}
|
||||||
|
@ -1708,16 +1760,11 @@ bool CharacterController::updateWeaponState()
|
||||||
else if(mUpperBodyState == UpperCharState_UnEquipingWeap)
|
else if(mUpperBodyState == UpperCharState_UnEquipingWeap)
|
||||||
mUpperBodyState = UpperCharState_Nothing;
|
mUpperBodyState = UpperCharState_Nothing;
|
||||||
}
|
}
|
||||||
else if(complete >= 1.0f)
|
else if(complete >= 1.0f && !isRandomAttackAnimation(mCurrentWeapon))
|
||||||
{
|
{
|
||||||
std::string start, stop;
|
std::string start, stop;
|
||||||
switch(mUpperBodyState)
|
switch(mUpperBodyState)
|
||||||
{
|
{
|
||||||
case UpperCharState_StartToMinAttack:
|
|
||||||
start = mAttackType+" min attack";
|
|
||||||
stop = mAttackType+" max attack";
|
|
||||||
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
|
||||||
break;
|
|
||||||
case UpperCharState_MinAttackToMaxAttack:
|
case UpperCharState_MinAttackToMaxAttack:
|
||||||
//hack to avoid body pos desync when jumping/sneaking in 'max attack' state
|
//hack to avoid body pos desync when jumping/sneaking in 'max attack' state
|
||||||
if(!mAnimation->isPlaying(mCurrentWeapon))
|
if(!mAnimation->isPlaying(mCurrentWeapon))
|
||||||
|
@ -1725,6 +1772,23 @@ bool CharacterController::updateWeaponState()
|
||||||
MWRender::Animation::BlendMask_All, false,
|
MWRender::Animation::BlendMask_All, false,
|
||||||
0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0);
|
0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0);
|
||||||
break;
|
break;
|
||||||
|
case UpperCharState_StartToMinAttack:
|
||||||
|
{
|
||||||
|
// If actor is already stopped preparing attack, do not play the "min attack -> max attack" part.
|
||||||
|
// Happens if the player did not hold the attack button.
|
||||||
|
// Note: if the "min attack"->"max attack" is a stub, "play" it anyway. Attack strength will be 1.
|
||||||
|
float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"min attack");
|
||||||
|
float maxAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"max attack");
|
||||||
|
if (mAttackingOrSpell || minAttackTime == maxAttackTime)
|
||||||
|
{
|
||||||
|
start = mAttackType+" min attack";
|
||||||
|
stop = mAttackType+" max attack";
|
||||||
|
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
playSwishSound(0.0f);
|
||||||
|
}
|
||||||
|
// Fall-through
|
||||||
case UpperCharState_MaxAttackToMinHit:
|
case UpperCharState_MaxAttackToMinHit:
|
||||||
if(mAttackType == "shoot")
|
if(mAttackType == "shoot")
|
||||||
{
|
{
|
||||||
|
@ -1779,6 +1843,11 @@ bool CharacterController::updateWeaponState()
|
||||||
weapSpeed, start, stop, 0.0f, 0);
|
weapSpeed, start, stop, 0.0f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(complete >= 1.0f && isRandomAttackAnimation(mCurrentWeapon))
|
||||||
|
{
|
||||||
|
mAnimation->disable(mCurrentWeapon);
|
||||||
|
mUpperBodyState = UpperCharState_WeapEquiped;
|
||||||
|
}
|
||||||
|
|
||||||
if (mPtr.getClass().hasInventoryStore(mPtr))
|
if (mPtr.getClass().hasInventoryStore(mPtr))
|
||||||
{
|
{
|
||||||
|
@ -2152,7 +2221,16 @@ void CharacterController::update(float duration)
|
||||||
|
|
||||||
if(mAnimQueue.empty() || inwater || sneak)
|
if(mAnimQueue.empty() || inwater || sneak)
|
||||||
{
|
{
|
||||||
idlestate = (inwater ? CharState_IdleSwim : (sneak && !inJump ? CharState_IdleSneak : CharState_Idle));
|
// Note: turning animations should not interrupt idle ones.
|
||||||
|
// Also movement should not stop idle animation for spellcasting stance.
|
||||||
|
if (inwater)
|
||||||
|
idlestate = CharState_IdleSwim;
|
||||||
|
else if (sneak && !inJump)
|
||||||
|
idlestate = CharState_IdleSneak;
|
||||||
|
else if (movestate != CharState_None && !isTurning() && mWeaponType != WeapType_Spell)
|
||||||
|
idlestate = CharState_None;
|
||||||
|
else
|
||||||
|
idlestate = CharState_Idle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
updateAnimQueue();
|
updateAnimQueue();
|
||||||
|
@ -2565,7 +2643,14 @@ void CharacterController::setAttackTypeBasedOnMovement()
|
||||||
mAttackType = "chop";
|
mAttackType = "chop";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::isAttackPrepairing() const
|
bool CharacterController::isRandomAttackAnimation(const std::string& group) const
|
||||||
|
{
|
||||||
|
return (group == "attack1" || group == "swimattack1" ||
|
||||||
|
group == "attack2" || group == "swimattack2" ||
|
||||||
|
group == "attack3" || group == "swimattack3");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharacterController::isAttackPreparing() const
|
||||||
{
|
{
|
||||||
return mUpperBodyState == UpperCharState_StartToMinAttack ||
|
return mUpperBodyState == UpperCharState_StartToMinAttack ||
|
||||||
mUpperBodyState == UpperCharState_MinAttackToMaxAttack;
|
mUpperBodyState == UpperCharState_MinAttackToMaxAttack;
|
||||||
|
@ -2666,7 +2751,7 @@ void CharacterController::setAttackTypeRandomly(std::string& attackType)
|
||||||
bool CharacterController::readyToPrepareAttack() const
|
bool CharacterController::readyToPrepareAttack() const
|
||||||
{
|
{
|
||||||
return (mHitState == CharState_None || mHitState == CharState_Block)
|
return (mHitState == CharState_None || mHitState == CharState_Block)
|
||||||
&& mUpperBodyState <= UpperCharState_WeapEquiped;
|
&& mUpperBodyState <= UpperCharState_WeapEquiped;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::readyToStartAttack() const
|
bool CharacterController::readyToStartAttack() const
|
||||||
|
|
|
@ -224,6 +224,9 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||||
bool updateCreatureState();
|
bool updateCreatureState();
|
||||||
void updateIdleStormState(bool inwater);
|
void updateIdleStormState(bool inwater);
|
||||||
|
|
||||||
|
std::string chooseRandomAttackAnimation() const;
|
||||||
|
bool isRandomAttackAnimation(const std::string& group) const;
|
||||||
|
|
||||||
bool isPersistentAnimPlaying();
|
bool isPersistentAnimPlaying();
|
||||||
|
|
||||||
void updateAnimQueue();
|
void updateAnimQueue();
|
||||||
|
@ -278,7 +281,7 @@ public:
|
||||||
|
|
||||||
void forceStateUpdate();
|
void forceStateUpdate();
|
||||||
|
|
||||||
bool isAttackPrepairing() const;
|
bool isAttackPreparing() const;
|
||||||
bool isCastingSpell() const;
|
bool isCastingSpell() const;
|
||||||
bool isReadyToBlock() const;
|
bool isReadyToBlock() const;
|
||||||
bool isKnockedDown() const;
|
bool isKnockedDown() const;
|
||||||
|
|
|
@ -503,9 +503,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
void getHandToHandDamage(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, float &damage, bool &healthdmg, float attackStrength)
|
void getHandToHandDamage(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, float &damage, bool &healthdmg, float attackStrength)
|
||||||
{
|
{
|
||||||
// Note: MCP contains an option to include Strength in hand-to-hand damage
|
|
||||||
// calculations. Some mods recommend using it, so we may want to include an
|
|
||||||
// option for it.
|
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
float minstrike = store.get<ESM::GameSetting>().find("fMinHandToHandMult")->getFloat();
|
float minstrike = store.get<ESM::GameSetting>().find("fMinHandToHandMult")->getFloat();
|
||||||
float maxstrike = store.get<ESM::GameSetting>().find("fMaxHandToHandMult")->getFloat();
|
float maxstrike = store.get<ESM::GameSetting>().find("fMaxHandToHandMult")->getFloat();
|
||||||
|
@ -516,6 +513,16 @@ namespace MWMechanics
|
||||||
healthdmg = otherstats.isParalyzed()
|
healthdmg = otherstats.isParalyzed()
|
||||||
|| otherstats.getKnockedDown();
|
|| otherstats.getKnockedDown();
|
||||||
bool isWerewolf = (attacker.getClass().isNpc() && attacker.getClass().getNpcStats(attacker).isWerewolf());
|
bool isWerewolf = (attacker.getClass().isNpc() && attacker.getClass().getNpcStats(attacker).isWerewolf());
|
||||||
|
|
||||||
|
// Options in the launcher's combo box: unarmedFactorsStrengthComboBox
|
||||||
|
// 0 = Do not factor strength into hand-to-hand combat.
|
||||||
|
// 1 = Factor into werewolf hand-to-hand combat.
|
||||||
|
// 2 = Ignore werewolves.
|
||||||
|
int factorStrength = Settings::Manager::getInt("strength influences hand to hand", "Game");
|
||||||
|
if (factorStrength == 1 || (factorStrength == 2 && !isWerewolf)) {
|
||||||
|
damage *= attacker.getClass().getCreatureStats(attacker).getAttribute(ESM::Attribute::Strength).getModified() / 40.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
healthdmg = true;
|
healthdmg = true;
|
||||||
|
|
|
@ -206,6 +206,7 @@ namespace MWMechanics
|
||||||
mDead = true;
|
mDead = true;
|
||||||
|
|
||||||
mDynamic[index].setModifier(0);
|
mDynamic[index].setModifier(0);
|
||||||
|
mDynamic[index].setCurrentModifier(0);
|
||||||
mDynamic[index].setCurrent(0);
|
mDynamic[index].setCurrent(0);
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWorld()->getGodModeState())
|
if (MWBase::Environment::get().getWorld()->getGodModeState())
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
|
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
|
||||||
#define OPENMW_MECHANICS_LEVELLEDLIST_H
|
#define OPENMW_MECHANICS_LEVELLEDLIST_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
@ -63,7 +62,7 @@ namespace MWMechanics
|
||||||
// Vanilla doesn't fail on nonexistent items in levelled lists
|
// Vanilla doesn't fail on nonexistent items in levelled lists
|
||||||
if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item)))
|
if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item)))
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: ignoring nonexistent item '" << item << "' in levelled list '" << levItem->mId << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: ignoring nonexistent item '" << item << "' in levelled list '" << levItem->mId << "'";
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "mechanicsmanagerimp.hpp"
|
#include "mechanicsmanagerimp.hpp"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
|
@ -448,9 +449,9 @@ namespace MWMechanics
|
||||||
return mActors.isActorDetected(actor, observer);
|
return mActors.isActorDetected(actor, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MechanicsManager::isAttackPrepairing(const MWWorld::Ptr& ptr)
|
bool MechanicsManager::isAttackPreparing(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
return mActors.isAttackPrepairing(ptr);
|
return mActors.isAttackPreparing(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
@ -1528,11 +1529,12 @@ namespace MWMechanics
|
||||||
if (target == getPlayer() || !attacker.getClass().isActor())
|
if (target == getPlayer() || !attacker.getClass().isActor())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::list<MWWorld::Ptr> followersAttacker = getActorsSidingWith(attacker);
|
std::set<MWWorld::Ptr> followersAttacker;
|
||||||
|
getActorsSidingWith(attacker, followersAttacker);
|
||||||
|
|
||||||
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
|
MWMechanics::CreatureStats& statsTarget = target.getClass().getCreatureStats(target);
|
||||||
|
|
||||||
if (std::find(followersAttacker.begin(), followersAttacker.end(), target) != followersAttacker.end())
|
if (followersAttacker.find(target) != followersAttacker.end())
|
||||||
{
|
{
|
||||||
statsTarget.friendlyHit();
|
statsTarget.friendlyHit();
|
||||||
|
|
||||||
|
@ -1543,24 +1545,11 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attacking an NPC that is already in combat with any other NPC is not a crime
|
if (canCommitCrimeAgainst(target, attacker))
|
||||||
AiSequence& seq = statsTarget.getAiSequence();
|
|
||||||
bool isFightingNpc = false;
|
|
||||||
for (std::list<AiPackage*>::const_iterator it = seq.begin(); it != seq.end(); ++it)
|
|
||||||
{
|
|
||||||
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr target2 = (*it)->getTarget();
|
|
||||||
if (!target2.isEmpty() && target2.getClass().isNpc())
|
|
||||||
isFightingNpc = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.getClass().isNpc() && !attacker.isEmpty() && !seq.isInCombat(attacker)
|
|
||||||
&& !isAggressive(target, attacker) && !isFightingNpc
|
|
||||||
&& !target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
|
||||||
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
|
commitCrime(attacker, target, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
|
AiSequence& seq = statsTarget.getAiSequence();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
|
@ -1597,6 +1586,14 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::canCommitCrimeAgainst(const MWWorld::Ptr &target, const MWWorld::Ptr &attacker)
|
||||||
|
{
|
||||||
|
MWMechanics::AiSequence seq = target.getClass().getCreatureStats(target).getAiSequence();
|
||||||
|
return target.getClass().isNpc() && !attacker.isEmpty() && !seq.isInCombat(attacker)
|
||||||
|
&& !isAggressive(target, attacker) && !seq.isEngagedWithActor()
|
||||||
|
&& !target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::actorKilled(const MWWorld::Ptr &victim, const MWWorld::Ptr &attacker)
|
void MechanicsManager::actorKilled(const MWWorld::Ptr &victim, const MWWorld::Ptr &attacker)
|
||||||
{
|
{
|
||||||
if (attacker.isEmpty() || victim.isEmpty())
|
if (attacker.isEmpty() || victim.isEmpty())
|
||||||
|
@ -1609,11 +1606,10 @@ namespace MWMechanics
|
||||||
return; // TODO: implement animal rights
|
return; // TODO: implement animal rights
|
||||||
|
|
||||||
const MWMechanics::NpcStats& victimStats = victim.getClass().getNpcStats(victim);
|
const MWMechanics::NpcStats& victimStats = victim.getClass().getNpcStats(victim);
|
||||||
if (victimStats.getCrimeId() == -1)
|
const MWWorld::Ptr &player = getPlayer();
|
||||||
return;
|
bool canCommit = attacker == player && canCommitCrimeAgainst(victim, attacker);
|
||||||
|
|
||||||
// For now we report only about crimes of player and player's followers
|
// For now we report only about crimes of player and player's followers
|
||||||
const MWWorld::Ptr &player = getPlayer();
|
|
||||||
if (attacker != player)
|
if (attacker != player)
|
||||||
{
|
{
|
||||||
std::set<MWWorld::Ptr> playerFollowers;
|
std::set<MWWorld::Ptr> playerFollowers;
|
||||||
|
@ -1622,6 +1618,9 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!canCommit && victimStats.getCrimeId() == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
// Simple check for who attacked first: if the player attacked first, a crimeId should be set
|
// Simple check for who attacked first: if the player attacked first, a crimeId should be set
|
||||||
// Doesn't handle possible edge case where no one reported the assault, but in such a case,
|
// Doesn't handle possible edge case where no one reported the assault, but in such a case,
|
||||||
// for bystanders it is not possible to tell who attacked first, anyway.
|
// for bystanders it is not possible to tell who attacked first, anyway.
|
||||||
|
|
|
@ -142,6 +142,12 @@ namespace MWMechanics
|
||||||
/// @note No-op for non-player attackers
|
/// @note No-op for non-player attackers
|
||||||
virtual void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
virtual void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
||||||
|
|
||||||
|
/// Checks if commiting a crime is currently valid
|
||||||
|
/// @param victim The actor being attacked
|
||||||
|
/// @param attacker The actor commiting the crime
|
||||||
|
/// @return true if the victim is a valid target for crime
|
||||||
|
virtual bool canCommitCrimeAgainst(const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
||||||
|
|
||||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||||
/// @param container The container the item is in; may be empty for an item in the world
|
/// @param container The container the item is in; may be empty for an item in the world
|
||||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||||
|
@ -243,7 +249,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
||||||
|
|
||||||
virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr);
|
virtual bool isAttackPreparing(const MWWorld::Ptr& ptr);
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr);
|
virtual bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "objects.hpp"
|
#include "objects.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -88,7 +88,7 @@ bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& gro
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr<< "Warning: Objects::playAnimationGroup: Unable to find " << ptr.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: Objects::playAnimationGroup: Unable to find " << ptr.getCellRef().getRefId();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
#include "../mwrender/vismask.hpp"
|
||||||
|
|
||||||
#include "npcstats.hpp"
|
#include "npcstats.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
@ -344,16 +345,19 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastSpell::launchMagicBolt ()
|
void CastSpell::launchMagicBolt ()
|
||||||
{
|
{
|
||||||
osg::Vec3f fallbackDirection (0,1,0);
|
osg::Vec3f fallbackDirection(0, 1, 0);
|
||||||
|
osg::Vec3f offset(0, 0, 0);
|
||||||
|
if (!mTarget.isEmpty() && mTarget.getClass().isActor())
|
||||||
|
offset.z() = MWBase::Environment::get().getWorld()->getHalfExtents(mTarget).z();
|
||||||
|
|
||||||
// Fall back to a "caster to target" direction if we have no other means of determining it
|
// Fall back to a "caster to target" direction if we have no other means of determining it
|
||||||
// (e.g. when cast by a non-actor)
|
// (e.g. when cast by a non-actor)
|
||||||
if (!mTarget.isEmpty())
|
if (!mTarget.isEmpty())
|
||||||
fallbackDirection =
|
fallbackDirection =
|
||||||
osg::Vec3f(mTarget.getRefData().getPosition().asVec3())-
|
(mTarget.getRefData().getPosition().asVec3() + offset) -
|
||||||
osg::Vec3f(mCaster.getRefData().getPosition().asVec3());
|
(mCaster.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->launchMagicBolt(mId, mCaster, fallbackDirection);
|
MWBase::Environment::get().getWorld()->launchMagicBolt(mId, mCaster, fallbackDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,9 +530,18 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else // target.getClass().isActor() == true
|
else // target.getClass().isActor() == true
|
||||||
{
|
{
|
||||||
|
ActiveSpells::ActiveEffect effect;
|
||||||
|
effect.mEffectId = effectIt->mEffectID;
|
||||||
|
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
||||||
|
effect.mMagnitude = magnitude;
|
||||||
|
|
||||||
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||||
if (hasDuration && effectIt->mDuration == 0)
|
if (hasDuration && effectIt->mDuration == 0)
|
||||||
{
|
{
|
||||||
|
// We still should add effect to list to allow GetSpellEffects to detect this spell
|
||||||
|
effect.mDuration = 0.f;
|
||||||
|
appliedLastingEffects.push_back(effect);
|
||||||
|
|
||||||
// duration 0 means apply full magnitude instantly
|
// duration 0 means apply full magnitude instantly
|
||||||
bool wasDead = target.getClass().getCreatureStats(target).isDead();
|
bool wasDead = target.getClass().getCreatureStats(target).isDead();
|
||||||
effectTick(target.getClass().getCreatureStats(target), target, EffectKey(*effectIt), magnitude);
|
effectTick(target.getClass().getCreatureStats(target), target, EffectKey(*effectIt), magnitude);
|
||||||
|
@ -563,18 +576,15 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// add to list of active effects, to apply in next frame
|
|
||||||
ActiveSpells::ActiveEffect effect;
|
|
||||||
effect.mEffectId = effectIt->mEffectID;
|
|
||||||
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
|
||||||
if (!hasDuration)
|
if (!hasDuration)
|
||||||
effect.mDuration = 1.0f;
|
effect.mDuration = 1.0f;
|
||||||
else
|
else
|
||||||
effect.mDuration = static_cast<float>(effectIt->mDuration);
|
effect.mDuration = static_cast<float>(effectIt->mDuration);
|
||||||
effect.mMagnitude = magnitude;
|
|
||||||
|
|
||||||
targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude));
|
targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude));
|
||||||
|
|
||||||
|
// add to list of active effects, to apply in next frame
|
||||||
appliedLastingEffects.push_back(effect);
|
appliedLastingEffects.push_back(effect);
|
||||||
|
|
||||||
// Unequip all items, if a spell with the ExtraSpell effect was casted
|
// Unequip all items, if a spell with the ExtraSpell effect was casted
|
||||||
|
@ -1123,11 +1133,13 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastSpell::playSpellCastingEffects(const std::string &spellid){
|
void CastSpell::playSpellCastingEffects(const std::string &spellid)
|
||||||
|
{
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
|
|
||||||
|
std::vector<std::string> addedEffects;
|
||||||
|
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->mEffects.mList.begin();
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->mEffects.mList.begin();
|
||||||
iter != spell->mEffects.mList.end(); ++iter)
|
iter != spell->mEffects.mList.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -1136,18 +1148,56 @@ namespace MWMechanics
|
||||||
|
|
||||||
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
||||||
|
|
||||||
if (animation && mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx even if they are disabled (animation == NULL)
|
const ESM::Static* castStatic;
|
||||||
|
|
||||||
|
if (!effect->mCasting.empty())
|
||||||
|
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
||||||
|
else
|
||||||
|
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
||||||
|
|
||||||
|
// check if the effect was already added
|
||||||
|
if (std::find(addedEffects.begin(), addedEffects.end(), "meshes\\" + castStatic->mModel) != addedEffects.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string texture = effect->mParticle;
|
||||||
|
|
||||||
|
float scale = 1.0f;
|
||||||
|
osg::Vec3f pos (mCaster.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
|
if (animation && mCaster.getClass().isNpc())
|
||||||
{
|
{
|
||||||
const ESM::Static* castStatic;
|
// For NPC we should take race height as scaling factor
|
||||||
|
const ESM::NPC *npc = mCaster.get<ESM::NPC>()->mBase;
|
||||||
|
const MWWorld::ESMStore &esmStore =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
|
||||||
if (!effect->mCasting.empty())
|
const ESM::Race *race =
|
||||||
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
esmStore.get<ESM::Race>().find(npc->mRace);
|
||||||
else
|
|
||||||
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
|
||||||
|
|
||||||
std::string texture = effect->mParticle;
|
scale = npc->isMale() ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::Vec3f halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(mCaster);
|
||||||
|
|
||||||
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture);
|
// TODO: take a size of particle or NPC with height and weight = 1.0 as scale = 1.0
|
||||||
|
float scaleX = halfExtents.x() * 2 / 60.f;
|
||||||
|
float scaleY = halfExtents.y() * 2 / 60.f;
|
||||||
|
float scaleZ = halfExtents.z() * 2 / 120.f;
|
||||||
|
|
||||||
|
scale = std::max({ scaleX, scaleY, scaleZ });
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the caster has no animation, add the effect directly to the effectManager
|
||||||
|
if (animation)
|
||||||
|
{
|
||||||
|
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture, scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We should set scale for effect manager manually
|
||||||
|
float meshScale = !mCaster.getClass().isActor() ? mCaster.getCellRef().getScale() : 1.0f;
|
||||||
|
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + castStatic->mModel, effect->mParticle, pos, scale * meshScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animation && !mCaster.getClass().isActor())
|
if (animation && !mCaster.getClass().isActor())
|
||||||
|
@ -1157,6 +1207,8 @@ namespace MWMechanics
|
||||||
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addedEffects.push_back("meshes\\" + castStatic->mModel);
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
if(!effect->mCastSound.empty())
|
if(!effect->mCastSound.empty())
|
||||||
sndMgr->playSound3D(mCaster, effect->mCastSound, 1.0f, 1.0f);
|
sndMgr->playSound3D(mCaster, effect->mCastSound, 1.0f, 1.0f);
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Stat<T>::Stat() : mBase (0), mModified (0) {}
|
Stat<T>::Stat() : mBase (0), mModified (0), mCurrentModified (0) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Stat<T>::Stat(T base) : mBase (base), mModified (base) {}
|
Stat<T>::Stat(T base) : mBase (base), mModified (base), mCurrentModified (base) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Stat<T>::Stat(T base, T modified) : mBase (base), mModified (modified) {}
|
Stat<T>::Stat(T base, T modified) : mBase (base), mModified (modified), mCurrentModified (modified) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& Stat<T>::getBase() const
|
const T& Stat<T>::getBase() const
|
||||||
|
@ -22,23 +22,42 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
return std::max(static_cast<T>(0), mModified);
|
return std::max(static_cast<T>(0), mModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Stat<T>::getCurrentModified() const
|
||||||
|
{
|
||||||
|
return mCurrentModified;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T Stat<T>::getModifier() const
|
T Stat<T>::getModifier() const
|
||||||
{
|
{
|
||||||
return mModified-mBase;
|
return mModified-mBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Stat<T>::getCurrentModifier() const
|
||||||
|
{
|
||||||
|
return mCurrentModified - mModified;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::set (const T& value)
|
void Stat<T>::set (const T& value)
|
||||||
{
|
{
|
||||||
|
T diff = value - mBase;
|
||||||
mBase = mModified = value;
|
mBase = mModified = value;
|
||||||
|
mCurrentModified += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::setBase (const T& value)
|
void Stat<T>::setBase (const T& value)
|
||||||
{
|
{
|
||||||
T diff = value - mBase;
|
T diff = value - mBase;
|
||||||
mBase = value;
|
mBase = value;
|
||||||
mModified += diff;
|
mModified += diff;
|
||||||
|
mCurrentModified += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::setModified (T value, const T& min, const T& max)
|
void Stat<T>::setModified (T value, const T& min, const T& max)
|
||||||
{
|
{
|
||||||
|
@ -57,24 +76,39 @@ namespace MWMechanics
|
||||||
|
|
||||||
mModified = value;
|
mModified = value;
|
||||||
mBase += diff;
|
mBase += diff;
|
||||||
|
mCurrentModified += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Stat<T>::setCurrentModified(T value)
|
||||||
|
{
|
||||||
|
mCurrentModified = value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::setModifier (const T& modifier)
|
void Stat<T>::setModifier (const T& modifier)
|
||||||
{
|
{
|
||||||
mModified = mBase + modifier;
|
mModified = mBase + modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Stat<T>::setCurrentModifier(const T& modifier)
|
||||||
|
{
|
||||||
|
mCurrentModified = mModified + modifier;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::writeState (ESM::StatState<T>& state) const
|
void Stat<T>::writeState (ESM::StatState<T>& state) const
|
||||||
{
|
{
|
||||||
state.mBase = mBase;
|
state.mBase = mBase;
|
||||||
state.mMod = mModified;
|
state.mMod = mCurrentModified;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Stat<T>::readState (const ESM::StatState<T>& state)
|
void Stat<T>::readState (const ESM::StatState<T>& state)
|
||||||
{
|
{
|
||||||
mBase = state.mBase;
|
mBase = state.mBase;
|
||||||
mModified = state.mMod;
|
mModified = state.mBase;
|
||||||
|
mCurrentModified = state.mMod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +132,12 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
return mStatic.getModified();
|
return mStatic.getModified();
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
T DynamicStat<T>::getCurrentModified() const
|
||||||
|
{
|
||||||
|
return mStatic.getCurrentModified();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& DynamicStat<T>::getCurrent() const
|
const T& DynamicStat<T>::getCurrent() const
|
||||||
{
|
{
|
||||||
|
@ -127,14 +167,21 @@ namespace MWMechanics
|
||||||
mCurrent = getModified();
|
mCurrent = getModified();
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void DynamicStat<T>::setCurrent (const T& value, bool allowDecreaseBelowZero)
|
void DynamicStat<T>::setCurrentModified(T value)
|
||||||
|
{
|
||||||
|
mStatic.setCurrentModified(value);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void DynamicStat<T>::setCurrent (const T& value, bool allowDecreaseBelowZero, bool allowIncreaseAboveModified)
|
||||||
{
|
{
|
||||||
if (value > mCurrent)
|
if (value > mCurrent)
|
||||||
{
|
{
|
||||||
// increase
|
// increase
|
||||||
mCurrent = value;
|
if (value <= getModified() || allowIncreaseAboveModified)
|
||||||
|
mCurrent = value;
|
||||||
if (mCurrent > getModified())
|
else if (mCurrent > getModified())
|
||||||
|
return;
|
||||||
|
else
|
||||||
mCurrent = getModified();
|
mCurrent = getModified();
|
||||||
}
|
}
|
||||||
else if (value > 0 || allowDecreaseBelowZero)
|
else if (value > 0 || allowDecreaseBelowZero)
|
||||||
|
@ -156,6 +203,16 @@ namespace MWMechanics
|
||||||
setCurrent (getCurrent()+diff, allowCurrentDecreaseBelowZero);
|
setCurrent (getCurrent()+diff, allowCurrentDecreaseBelowZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void DynamicStat<T>::setCurrentModifier(const T& modifier, bool allowCurrentDecreaseBelowZero)
|
||||||
|
{
|
||||||
|
T diff = modifier - mStatic.getCurrentModifier();
|
||||||
|
mStatic.setCurrentModifier(modifier);
|
||||||
|
|
||||||
|
// The (modifier > 0) check here allows increase over modified only if the modifier is positive (a fortify effect is active).
|
||||||
|
setCurrent (getCurrent() + diff, allowCurrentDecreaseBelowZero, (modifier > 0));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void DynamicStat<T>::writeState (ESM::StatState<T>& state) const
|
void DynamicStat<T>::writeState (ESM::StatState<T>& state) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
T mBase;
|
T mBase;
|
||||||
T mModified;
|
T mModified;
|
||||||
|
T mCurrentModified;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T Type;
|
typedef T Type;
|
||||||
|
@ -28,7 +29,9 @@ namespace MWMechanics
|
||||||
const T& getBase() const;
|
const T& getBase() const;
|
||||||
|
|
||||||
T getModified() const;
|
T getModified() const;
|
||||||
|
T getCurrentModified() const;
|
||||||
T getModifier() const;
|
T getModifier() const;
|
||||||
|
T getCurrentModifier() const;
|
||||||
|
|
||||||
/// Set base and modified to \a value.
|
/// Set base and modified to \a value.
|
||||||
void set (const T& value);
|
void set (const T& value);
|
||||||
|
@ -36,9 +39,15 @@ namespace MWMechanics
|
||||||
/// Set base and adjust modified accordingly.
|
/// Set base and adjust modified accordingly.
|
||||||
void setBase (const T& value);
|
void setBase (const T& value);
|
||||||
|
|
||||||
/// Set modified value an adjust base accordingly.
|
/// Set modified value and adjust base accordingly.
|
||||||
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max());
|
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max());
|
||||||
|
|
||||||
|
/// Set "current modified," used for drain and fortify. Unlike the regular modifier
|
||||||
|
/// this just adds and subtracts from the current value without changing the maximum.
|
||||||
|
void setCurrentModified(T value);
|
||||||
|
|
||||||
void setModifier (const T& modifier);
|
void setModifier (const T& modifier);
|
||||||
|
void setCurrentModifier (const T& modifier);
|
||||||
|
|
||||||
void writeState (ESM::StatState<T>& state) const;
|
void writeState (ESM::StatState<T>& state) const;
|
||||||
void readState (const ESM::StatState<T>& state);
|
void readState (const ESM::StatState<T>& state);
|
||||||
|
@ -73,6 +82,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
const T& getBase() const;
|
const T& getBase() const;
|
||||||
T getModified() const;
|
T getModified() const;
|
||||||
|
T getCurrentModified() const;
|
||||||
const T& getCurrent() const;
|
const T& getCurrent() const;
|
||||||
|
|
||||||
/// Set base, modified and current to \a value.
|
/// Set base, modified and current to \a value.
|
||||||
|
@ -81,11 +91,16 @@ namespace MWMechanics
|
||||||
/// Set base and adjust modified accordingly.
|
/// Set base and adjust modified accordingly.
|
||||||
void setBase (const T& value);
|
void setBase (const T& value);
|
||||||
|
|
||||||
/// Set modified value an adjust base accordingly.
|
/// Set modified value and adjust base accordingly.
|
||||||
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max());
|
void setModified (T value, const T& min, const T& max = std::numeric_limits<T>::max());
|
||||||
|
|
||||||
void setCurrent (const T& value, bool allowDecreaseBelowZero = false);
|
/// Set "current modified," used for drain and fortify. Unlike the regular modifier
|
||||||
void setModifier (const T& modifier, bool allowCurrentDecreaseBelowZero=false);
|
/// this just adds and subtracts from the current value without changing the maximum.
|
||||||
|
void setCurrentModified(T value);
|
||||||
|
|
||||||
|
void setCurrent (const T& value, bool allowDecreaseBelowZero = false, bool allowIncreaseAboveModified = false);
|
||||||
|
void setModifier (const T& modifier, bool allowCurrentToDecreaseBelowZero=false);
|
||||||
|
void setCurrentModifier (const T& modifier, bool allowCurrentToDecreaseBelowZero = false);
|
||||||
|
|
||||||
void writeState (ESM::StatState<T>& state) const;
|
void writeState (ESM::StatState<T>& state) const;
|
||||||
void readState (const ESM::StatState<T>& state);
|
void readState (const ESM::StatState<T>& state);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "summoning.hpp"
|
#include "summoning.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -120,7 +120,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to spawn summoned creature: " << e.what() << std::endl;
|
Log(Debug::Error) << "Failed to spawn summoned creature: " << e.what();
|
||||||
// still insert into creatureMap so we don't try to spawn again every frame, that would spam the warning log
|
// still insert into creatureMap so we don't try to spawn again every frame, that would spam the warning log
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "physicssystem.hpp"
|
#include "physicssystem.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
@ -20,7 +19,7 @@
|
||||||
#include <components/nifbullet/bulletnifloader.hpp>
|
#include <components/nifbullet/bulletnifloader.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/loadgmst.hpp>
|
#include <components/esm/loadgmst.hpp>
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
#include <components/sceneutil/unrefqueue.hpp>
|
#include <components/sceneutil/unrefqueue.hpp>
|
||||||
|
@ -638,7 +637,7 @@ namespace MWPhysics
|
||||||
mPtr.getRefData().getBaseNode()->accept(visitor);
|
mPtr.getRefData().getBaseNode()->accept(visitor);
|
||||||
if (!visitor.mFound)
|
if (!visitor.mFound)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: animateCollisionShapes can't find node " << recIndex << " for " << mPtr.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: animateCollisionShapes can't find node " << recIndex << " for " << mPtr.getCellRef().getRefId();
|
||||||
|
|
||||||
// Remove nonexistent nodes from animated shapes map and early out
|
// Remove nonexistent nodes from animated shapes map and early out
|
||||||
mShapeInstance->mAnimatedShapes.erase(recIndex);
|
mShapeInstance->mAnimatedShapes.erase(recIndex);
|
||||||
|
@ -708,7 +707,7 @@ namespace MWPhysics
|
||||||
if (physFramerate > 0)
|
if (physFramerate > 0)
|
||||||
{
|
{
|
||||||
mPhysicsDt = 1.f / physFramerate;
|
mPhysicsDt = 1.f / physFramerate;
|
||||||
std::cerr << "Warning: physics framerate was overridden (a new value is " << physFramerate << ")." << std::endl;
|
Log(Debug::Warning) << "Warning: using custom physics framerate (" << physFramerate << " FPS).";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
#include <osg/BlendFunc>
|
#include <osg/BlendFunc>
|
||||||
#include <osg/Material>
|
#include <osg/Material>
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
#include <osgParticle/ParticleProcessor>
|
#include <osgParticle/ParticleProcessor>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
@ -192,7 +195,7 @@ namespace
|
||||||
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||||
{
|
{
|
||||||
if (!it->second->removeChild(it->first))
|
if (!it->second->removeChild(it->first))
|
||||||
std::cerr << "error removing " << it->first->getName() << std::endl;
|
Log(Debug::Error) << "Error removing " << it->first->getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +205,110 @@ namespace
|
||||||
std::vector<std::pair<osg::Node*, osg::Group*> > mToRemove;
|
std::vector<std::pair<osg::Node*, osg::Group*> > mToRemove;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RemoveFinishedCallbackVisitor : public RemoveVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RemoveFinishedCallbackVisitor()
|
||||||
|
: RemoveVisitor()
|
||||||
|
, mEffectId(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveFinishedCallbackVisitor(int effectId)
|
||||||
|
: RemoveVisitor()
|
||||||
|
, mEffectId(effectId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Node &node)
|
||||||
|
{
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Group &group)
|
||||||
|
{
|
||||||
|
traverse(group);
|
||||||
|
|
||||||
|
osg::Callback* callback = group.getUpdateCallback();
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
// We should remove empty transformation nodes and finished callbacks here
|
||||||
|
MWRender::UpdateVfxCallback* vfxCallback = dynamic_cast<MWRender::UpdateVfxCallback*>(callback);
|
||||||
|
bool finished = vfxCallback && vfxCallback->mFinished;
|
||||||
|
bool toRemove = vfxCallback && mEffectId >= 0 && vfxCallback->mParams.mEffectId == mEffectId;
|
||||||
|
if (finished || toRemove)
|
||||||
|
{
|
||||||
|
mToRemove.push_back(std::make_pair(group.asNode(), group.getParent(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::MatrixTransform &node)
|
||||||
|
{
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Geometry&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mEffectId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FindVfxCallbacksVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
std::vector<MWRender::UpdateVfxCallback*> mCallbacks;
|
||||||
|
|
||||||
|
FindVfxCallbacksVisitor()
|
||||||
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
, mEffectId(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FindVfxCallbacksVisitor(int effectId)
|
||||||
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
, mEffectId(effectId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Node &node)
|
||||||
|
{
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Group &group)
|
||||||
|
{
|
||||||
|
osg::Callback* callback = group.getUpdateCallback();
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
MWRender::UpdateVfxCallback* vfxCallback = dynamic_cast<MWRender::UpdateVfxCallback*>(callback);
|
||||||
|
if (vfxCallback)
|
||||||
|
{
|
||||||
|
if (mEffectId < 0 || vfxCallback->mParams.mEffectId == mEffectId)
|
||||||
|
{
|
||||||
|
mCallbacks.push_back(vfxCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traverse(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::MatrixTransform &node)
|
||||||
|
{
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Geometry&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mEffectId;
|
||||||
|
};
|
||||||
|
|
||||||
// Removes all drawables from a graph.
|
// Removes all drawables from a graph.
|
||||||
class CleanObjectRootVisitor : public RemoveVisitor
|
class CleanObjectRootVisitor : public RemoveVisitor
|
||||||
{
|
{
|
||||||
|
@ -285,7 +392,6 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -430,6 +536,42 @@ namespace MWRender
|
||||||
const std::multimap<float, std::string>& getTextKeys() const;
|
const std::multimap<float, std::string>& getTextKeys() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
traverse(node, nv);
|
||||||
|
|
||||||
|
if (mFinished)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double newTime = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
if (mStartingTime == 0)
|
||||||
|
{
|
||||||
|
mStartingTime = newTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double duration = newTime - mStartingTime;
|
||||||
|
mStartingTime = newTime;
|
||||||
|
|
||||||
|
mParams.mAnimTime->addTime(duration);
|
||||||
|
if (mParams.mAnimTime->getTime() >= mParams.mMaxControllerLength)
|
||||||
|
{
|
||||||
|
if (mParams.mLoop)
|
||||||
|
{
|
||||||
|
// Start from the beginning again; carry over the remainder
|
||||||
|
// Not sure if this is actually needed, the controller function might already handle loops
|
||||||
|
float remainder = mParams.mAnimTime->getTime() - mParams.mMaxControllerLength;
|
||||||
|
mParams.mAnimTime->resetTime(remainder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Remove effect immediately
|
||||||
|
mParams.mObjects.reset();
|
||||||
|
mFinished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ResetAccumRootCallback : public osg::NodeCallback
|
class ResetAccumRootCallback : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -612,7 +754,7 @@ namespace MWRender
|
||||||
NodeMap::const_iterator found = nodeMap.find(bonename);
|
NodeMap::const_iterator found = nodeMap.find(bonename);
|
||||||
if (found == nodeMap.end())
|
if (found == nodeMap.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: addAnimSource: can't find bone '" + bonename << "' in " << baseModel << " (referenced by " << kfname << ")" << std::endl;
|
Log(Debug::Warning) << "Warning: addAnimSource: can't find bone '" + bonename << "' in " << baseModel << " (referenced by " << kfname << ")";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,7 +866,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error handling text key " << evt << ": " << e.what() << std::endl;
|
Log(Debug::Error) << "Error handling text key " << evt << ": " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1434,15 +1576,22 @@ namespace MWRender
|
||||||
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
|
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture)
|
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture, float scale)
|
||||||
{
|
{
|
||||||
if (!mObjectRoot.get())
|
if (!mObjectRoot.get())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Early out if we already have this effect
|
// Early out if we already have this effect
|
||||||
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
FindVfxCallbacksVisitor visitor(effectId);
|
||||||
if (it->mLoop && loop && it->mEffectId == effectId && it->mBoneName == bonename)
|
mInsert->accept(visitor);
|
||||||
|
|
||||||
|
for (std::vector<UpdateVfxCallback*>::iterator it = visitor.mCallbacks.begin(); it != visitor.mCallbacks.end(); ++it)
|
||||||
|
{
|
||||||
|
UpdateVfxCallback* callback = *it;
|
||||||
|
|
||||||
|
if (loop && !callback->mFinished && callback->mParams.mLoop && callback->mParams.mBoneName == bonename)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EffectParams params;
|
EffectParams params;
|
||||||
params.mModelName = model;
|
params.mModelName = model;
|
||||||
|
@ -1457,83 +1606,64 @@ namespace MWRender
|
||||||
|
|
||||||
parentNode = found->second;
|
parentNode = found->second;
|
||||||
}
|
}
|
||||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model, parentNode);
|
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::PositionAttitudeTransform> trans = new osg::PositionAttitudeTransform;
|
||||||
|
trans->setScale(osg::Vec3f(scale, scale, scale));
|
||||||
|
parentNode->addChild(trans);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model, trans);
|
||||||
node->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
node->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
|
||||||
params.mObjects = PartHolderPtr(new PartHolder(node));
|
|
||||||
|
|
||||||
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
||||||
node->accept(findMaxLengthVisitor);
|
node->accept(findMaxLengthVisitor);
|
||||||
|
|
||||||
// FreezeOnCull doesn't work so well with effect particles, that tend to have moving emitters
|
// FreezeOnCull doesn't work so well with effect particles, that tend to have moving emitters
|
||||||
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
||||||
node->accept(disableFreezeOnCullVisitor);
|
node->accept(disableFreezeOnCullVisitor);
|
||||||
|
|
||||||
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
|
||||||
|
|
||||||
node->setNodeMask(Mask_Effect);
|
node->setNodeMask(Mask_Effect);
|
||||||
|
|
||||||
|
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
||||||
params.mLoop = loop;
|
params.mLoop = loop;
|
||||||
params.mEffectId = effectId;
|
params.mEffectId = effectId;
|
||||||
params.mBoneName = bonename;
|
params.mBoneName = bonename;
|
||||||
|
params.mObjects = PartHolderPtr(new PartHolder(node));
|
||||||
params.mAnimTime = std::shared_ptr<EffectAnimationTime>(new EffectAnimationTime);
|
params.mAnimTime = std::shared_ptr<EffectAnimationTime>(new EffectAnimationTime);
|
||||||
|
trans->addUpdateCallback(new UpdateVfxCallback(params));
|
||||||
|
|
||||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
||||||
node->accept(assignVisitor);
|
node->accept(assignVisitor);
|
||||||
|
|
||||||
overrideFirstRootTexture(texture, mResourceSystem, node);
|
overrideFirstRootTexture(texture, mResourceSystem, node);
|
||||||
|
|
||||||
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.
|
|
||||||
|
|
||||||
mEffects.push_back(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::removeEffect(int effectId)
|
void Animation::removeEffect(int effectId)
|
||||||
{
|
{
|
||||||
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
RemoveFinishedCallbackVisitor visitor(effectId);
|
||||||
{
|
mInsert->accept(visitor);
|
||||||
if (it->mEffectId == effectId)
|
visitor.remove();
|
||||||
{
|
|
||||||
mEffects.erase(it);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::getLoopingEffects(std::vector<int> &out) const
|
void Animation::getLoopingEffects(std::vector<int> &out) const
|
||||||
{
|
{
|
||||||
for (std::vector<EffectParams>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
FindVfxCallbacksVisitor visitor;
|
||||||
|
mInsert->accept(visitor);
|
||||||
|
|
||||||
|
for (std::vector<UpdateVfxCallback*>::iterator it = visitor.mCallbacks.begin(); it != visitor.mCallbacks.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->mLoop)
|
UpdateVfxCallback* callback = *it;
|
||||||
out.push_back(it->mEffectId);
|
|
||||||
|
if (callback->mParams.mLoop && !callback->mFinished)
|
||||||
|
out.push_back(callback->mParams.mEffectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::updateEffects(float duration)
|
void Animation::updateEffects(float duration)
|
||||||
{
|
{
|
||||||
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); )
|
// TODO: objects without animation still will have
|
||||||
{
|
// transformation nodes with finished callbacks
|
||||||
it->mAnimTime->addTime(duration);
|
RemoveFinishedCallbackVisitor visitor;
|
||||||
|
mInsert->accept(visitor);
|
||||||
if (it->mAnimTime->getTime() >= it->mMaxControllerLength)
|
visitor.remove();
|
||||||
{
|
|
||||||
if (it->mLoop)
|
|
||||||
{
|
|
||||||
// Start from the beginning again; carry over the remainder
|
|
||||||
// Not sure if this is actually needed, the controller function might already handle loops
|
|
||||||
float remainder = it->mAnimTime->getTime() - it->mMaxControllerLength;
|
|
||||||
it->mAnimTime->resetTime(remainder);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it = mEffects.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::upperBodyReady() const
|
bool Animation::upperBodyReady() const
|
||||||
|
@ -1767,14 +1897,13 @@ namespace MWRender
|
||||||
PartHolder::~PartHolder()
|
PartHolder::~PartHolder()
|
||||||
{
|
{
|
||||||
if (mNode.get() && !mNode->getNumParents())
|
if (mNode.get() && !mNode->getNumParents())
|
||||||
std::cerr << "Error: part has no parents " << std::endl;
|
Log(Debug::Verbose) << "Part has no parents" ;
|
||||||
|
|
||||||
if (mNode.get() && mNode->getNumParents())
|
if (mNode.get() && mNode->getNumParents())
|
||||||
{
|
{
|
||||||
if (mNode->getNumParents() > 1)
|
if (mNode->getNumParents() > 1)
|
||||||
std::cerr << "Error: part has multiple parents " << mNode->getNumParents() << " " << mNode.get() << std::endl;
|
Log(Debug::Verbose) << "Part has multiple (" << mNode->getNumParents() << ") parents";
|
||||||
mNode->getParent(0)->removeChild(mNode);
|
mNode->getParent(0)->removeChild(mNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,17 @@ private:
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr<PartHolder> PartHolderPtr;
|
typedef std::shared_ptr<PartHolder> PartHolderPtr;
|
||||||
|
|
||||||
|
struct EffectParams
|
||||||
|
{
|
||||||
|
std::string mModelName; // Just here so we don't add the same effect twice
|
||||||
|
PartHolderPtr mObjects;
|
||||||
|
std::shared_ptr<EffectAnimationTime> mAnimTime;
|
||||||
|
float mMaxControllerLength;
|
||||||
|
int mEffectId;
|
||||||
|
bool mLoop;
|
||||||
|
std::string mBoneName;
|
||||||
|
};
|
||||||
|
|
||||||
class Animation : public osg::Referenced
|
class Animation : public osg::Referenced
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -247,19 +258,6 @@ protected:
|
||||||
|
|
||||||
osg::Vec3f mAccumulate;
|
osg::Vec3f mAccumulate;
|
||||||
|
|
||||||
struct EffectParams
|
|
||||||
{
|
|
||||||
std::string mModelName; // Just here so we don't add the same effect twice
|
|
||||||
PartHolderPtr mObjects;
|
|
||||||
std::shared_ptr<EffectAnimationTime> mAnimTime;
|
|
||||||
float mMaxControllerLength;
|
|
||||||
int mEffectId;
|
|
||||||
bool mLoop;
|
|
||||||
std::string mBoneName;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<EffectParams> mEffects;
|
|
||||||
|
|
||||||
TextKeyListener* mTextKeyListener;
|
TextKeyListener* mTextKeyListener;
|
||||||
|
|
||||||
osg::ref_ptr<RotateController> mHeadController;
|
osg::ref_ptr<RotateController> mHeadController;
|
||||||
|
@ -369,7 +367,7 @@ public:
|
||||||
* @param texture override the texture specified in the model's materials - if empty, do not override
|
* @param texture override the texture specified in the model's materials - if empty, do not override
|
||||||
* @note Will not add an effect twice.
|
* @note Will not add an effect twice.
|
||||||
*/
|
*/
|
||||||
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = "");
|
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = "", float scale = 1.0f);
|
||||||
void removeEffect (int effectId);
|
void removeEffect (int effectId);
|
||||||
void getLoopingEffects (std::vector<int>& out) const;
|
void getLoopingEffects (std::vector<int>& out) const;
|
||||||
|
|
||||||
|
@ -489,5 +487,24 @@ public:
|
||||||
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight);
|
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UpdateVfxCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpdateVfxCallback(EffectParams& params)
|
||||||
|
: mFinished(false)
|
||||||
|
, mParams(params)
|
||||||
|
, mStartingTime(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mFinished;
|
||||||
|
EffectParams mParams;
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double mStartingTime;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "bulletdebugdraw.hpp"
|
#include "bulletdebugdraw.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||||
|
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -91,7 +91,7 @@ void DebugDrawer::drawContactPoint(const btVector3 &PointOnB, const btVector3 &n
|
||||||
|
|
||||||
void DebugDrawer::reportErrorWarning(const char *warningString)
|
void DebugDrawer::reportErrorWarning(const char *warningString)
|
||||||
{
|
{
|
||||||
std::cerr << warningString << std::endl;
|
Log(Debug::Warning) << warningString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDrawer::setDebugMode(int isOn)
|
void DebugDrawer::setDebugMode(int isOn)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "characterpreview.hpp"
|
#include "characterpreview.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <osg/Material>
|
#include <osg/Material>
|
||||||
#include <osg/Fog>
|
#include <osg/Fog>
|
||||||
|
@ -14,6 +13,7 @@
|
||||||
#include <osgUtil/IntersectionVisitor>
|
#include <osgUtil/IntersectionVisitor>
|
||||||
#include <osgUtil/LineSegmentIntersector>
|
#include <osgUtil/LineSegmentIntersector>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ namespace MWRender
|
||||||
mCamera->addUpdateCallback(mUpdateCameraCallback);
|
mCamera->addUpdateCallback(mUpdateCameraCallback);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cerr << "Error: Bip01 Head node not found" << std::endl;
|
Log(Debug::Error) << "Error: Bip01 Head node not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
#include "creatureanimation.hpp"
|
#include "creatureanimation.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
|
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/sceneutil/attach.hpp>
|
#include <components/sceneutil/attach.hpp>
|
||||||
|
@ -155,7 +153,7 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Can not add creature part: " << e.what() << std::endl;
|
Log(Debug::Error) << "Can not add creature part: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/files/memorystream.hpp>
|
#include <components/files/memorystream.hpp>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/sceneutil/workqueue.hpp>
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
|
|
||||||
#include <components/esm/globalmap.hpp>
|
#include <components/esm/globalmap.hpp>
|
||||||
|
@ -458,14 +460,14 @@ namespace MWRender
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't write map overlay: no png readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Can't write map overlay: no png readerwriter found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mOverlayImage, ostream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mOverlayImage, ostream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't write map overlay: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Warning) << "Error: Can't write map overlay: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,14 +512,14 @@ namespace MWRender
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't read map overlay: no png readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Can't read map overlay: no png readerwriter found";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(istream);
|
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(istream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Can't read map overlay: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Can't read map overlay: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +621,7 @@ namespace MWRender
|
||||||
CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), camera);
|
CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), camera);
|
||||||
if (found == mActiveCameras.end())
|
if (found == mActiveCameras.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: GlobalMap trying to remove an inactive camera" << std::endl;
|
Log(Debug::Error) << "Error: GlobalMap trying to remove an inactive camera";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mActiveCameras.erase(found);
|
mActiveCameras.erase(found);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "localmap.hpp"
|
#include "localmap.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <osg/Fog>
|
#include <osg/Fog>
|
||||||
|
@ -12,6 +11,7 @@
|
||||||
|
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/fogstate.hpp>
|
#include <components/esm/fogstate.hpp>
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
@ -320,7 +320,7 @@ void LocalMap::markForRemoval(osg::Camera *cam)
|
||||||
CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), cam);
|
CameraVector::iterator found = std::find(mActiveCameras.begin(), mActiveCameras.end(), cam);
|
||||||
if (found == mActiveCameras.end())
|
if (found == mActiveCameras.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: trying to remove an inactive camera" << std::endl;
|
Log(Debug::Error) << "Error: trying to remove an inactive camera";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mActiveCameras.erase(found);
|
mActiveCameras.erase(found);
|
||||||
|
@ -492,7 +492,7 @@ void LocalMap::requestInteriorMap(const MWWorld::CellStore* cell)
|
||||||
// We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same.
|
// We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same.
|
||||||
if (i >= int(fog->mFogTextures.size()))
|
if (i >= int(fog->mFogTextures.size()))
|
||||||
{
|
{
|
||||||
std::cout << "Error: fog texture count mismatch" << std::endl;
|
Log(Debug::Warning) << "Warning: fog texture count mismatch";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,7 +684,7 @@ void LocalMap::MapSegment::loadFogOfWar(const ESM::FogTexture &esm)
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Unable to load fog, can't find a tga ReaderWriter" << std::endl;
|
Log(Debug::Error) << "Error: Unable to load fog, can't find a tga ReaderWriter" ;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ void LocalMap::MapSegment::loadFogOfWar(const ESM::FogTexture &esm)
|
||||||
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(in);
|
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(in);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Failed to read fog: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Failed to read fog: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +716,7 @@ void LocalMap::MapSegment::saveFogOfWar(ESM::FogTexture &fog) const
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Unable to write fog, can't find a tga ReaderWriter" << std::endl;
|
Log(Debug::Error) << "Error: Unable to write fog, can't find a tga ReaderWriter";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +725,7 @@ void LocalMap::MapSegment::saveFogOfWar(ESM::FogTexture &fog) const
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mFogOfWarImage, ostream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mFogOfWarImage, ostream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Unable to write fog: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Unable to write fog: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mFogOfWarImage->flipVertical();
|
mFogOfWarImage->flipVertical();
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <osgUtil/RenderBin>
|
#include <osgUtil/RenderBin>
|
||||||
#include <osgUtil/CullVisitor>
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
@ -435,7 +437,7 @@ void NpcAnimation::updateNpcBase()
|
||||||
if (bp)
|
if (bp)
|
||||||
mHeadModel = "meshes\\" + bp->mModel;
|
mHeadModel = "meshes\\" + bp->mModel;
|
||||||
else
|
else
|
||||||
std::cerr << "Warning: Failed to load body part '" << mNpc->mHead << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: Failed to load body part '" << mNpc->mHead << "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
mHairModel = "";
|
mHairModel = "";
|
||||||
|
@ -445,7 +447,7 @@ void NpcAnimation::updateNpcBase()
|
||||||
if (bp)
|
if (bp)
|
||||||
mHairModel = "meshes\\" + bp->mModel;
|
mHairModel = "meshes\\" + bp->mModel;
|
||||||
else
|
else
|
||||||
std::cerr << "Warning: Failed to load body part '" << mNpc->mHair << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: Failed to load body part '" << mNpc->mHair << "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +760,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error adding NPC part: " << e.what() << std::endl;
|
Log(Debug::Error) << "Error adding NPC part: " << e.what();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,7 +847,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
||||||
bodypart = NULL;
|
bodypart = NULL;
|
||||||
}
|
}
|
||||||
else if (!bodypart)
|
else if (!bodypart)
|
||||||
std::cerr << "Warning: Failed to find body part '" << part->mFemale << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: Failed to find body part '" << part->mFemale << "'";
|
||||||
}
|
}
|
||||||
if(!bodypart && !part->mMale.empty())
|
if(!bodypart && !part->mMale.empty())
|
||||||
{
|
{
|
||||||
|
@ -860,7 +862,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
||||||
bodypart = NULL;
|
bodypart = NULL;
|
||||||
}
|
}
|
||||||
else if (!bodypart)
|
else if (!bodypart)
|
||||||
std::cerr << "Warning: Failed to find body part '" << part->mMale << "'" << std::endl;
|
Log(Debug::Warning) << "Warning: Failed to find body part '" << part->mMale << "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bodypart)
|
if(bodypart)
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include <osgViewer/Viewer>
|
#include <osgViewer/Viewer>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
@ -47,6 +49,7 @@
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwgui/loadingscreen.hpp"
|
#include "../mwgui/loadingscreen.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
@ -709,7 +712,7 @@ namespace MWRender
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
std::cerr << "Wrong screenshot type: " << settingArgs[0] << "." << std::endl;
|
Log(Debug::Warning) << "Wrong screenshot type: " << settingArgs[0] << ".";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,7 +731,7 @@ namespace MWRender
|
||||||
|
|
||||||
if (mCamera->isVanityOrPreviewModeEnabled())
|
if (mCamera->isVanityOrPreviewModeEnabled())
|
||||||
{
|
{
|
||||||
std::cerr << "Spherical screenshots are not allowed in preview mode." << std::endl;
|
Log(Debug::Warning) << "Spherical screenshots are not allowed in preview mode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,6 +1322,29 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f RenderingManager::getHalfExtents(const MWWorld::ConstPtr& object) const
|
||||||
|
{
|
||||||
|
osg::Vec3f halfExtents(0, 0, 0);
|
||||||
|
std::string modelName = object.getClass().getModel(object);
|
||||||
|
if (modelName.empty())
|
||||||
|
return halfExtents;
|
||||||
|
|
||||||
|
osg::ref_ptr<const osg::Node> node = mResourceSystem->getSceneManager()->getTemplate(modelName);
|
||||||
|
osg::ComputeBoundsVisitor computeBoundsVisitor;
|
||||||
|
computeBoundsVisitor.setTraversalMask(~(MWRender::Mask_ParticleSystem|MWRender::Mask_Effect));
|
||||||
|
const_cast<osg::Node*>(node.get())->accept(computeBoundsVisitor);
|
||||||
|
osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox();
|
||||||
|
|
||||||
|
if (bounds.valid())
|
||||||
|
{
|
||||||
|
halfExtents[0] = std::abs(bounds.xMax() - bounds.xMin()) / 2.f;
|
||||||
|
halfExtents[1] = std::abs(bounds.yMax() - bounds.yMin()) / 2.f;
|
||||||
|
halfExtents[2] = std::abs(bounds.zMax() - bounds.zMin()) / 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return halfExtents;
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingManager::resetFieldOfView()
|
void RenderingManager::resetFieldOfView()
|
||||||
{
|
{
|
||||||
if (mFieldOfViewOverridden == true)
|
if (mFieldOfViewOverridden == true)
|
||||||
|
|
|
@ -203,6 +203,8 @@ namespace MWRender
|
||||||
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
|
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
|
||||||
void resetFieldOfView();
|
void resetFieldOfView();
|
||||||
|
|
||||||
|
osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& object) const;
|
||||||
|
|
||||||
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format);
|
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format);
|
||||||
|
|
||||||
LandManager* getLandManager() const;
|
LandManager* getLandManager() const;
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <osgUtil/IncrementalCompileOperation>
|
#include <osgUtil/IncrementalCompileOperation>
|
||||||
#include <osgUtil/CullVisitor>
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
@ -29,7 +31,6 @@
|
||||||
|
|
||||||
#include <components/shader/shadermanager.hpp>
|
#include <components/shader/shadermanager.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
@ -193,16 +194,16 @@ osg::ref_ptr<osg::Image> readPngImage (const std::string& file)
|
||||||
boost::filesystem::ifstream inStream;
|
boost::filesystem::ifstream inStream;
|
||||||
inStream.open(file, std::ios_base::in | std::ios_base::binary);
|
inStream.open(file, std::ios_base::in | std::ios_base::binary);
|
||||||
if (inStream.fail())
|
if (inStream.fail())
|
||||||
std::cerr << "Error: Failed to open " << file << std::endl;
|
Log(Debug::Error) << "Error: Failed to open " << file;
|
||||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||||
if (!reader)
|
if (!reader)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Failed to read " << file << ", no png readerwriter found" << std::endl;
|
Log(Debug::Error) << "Error: Failed to read " << file << ", no png readerwriter found";
|
||||||
return osg::ref_ptr<osg::Image>();
|
return osg::ref_ptr<osg::Image>();
|
||||||
}
|
}
|
||||||
osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream);
|
osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
std::cerr << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status();
|
||||||
|
|
||||||
return result.getImage();
|
return result.getImage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "aiextensions.hpp"
|
#include "aiextensions.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -64,7 +65,7 @@ namespace MWScript
|
||||||
|
|
||||||
MWMechanics::AiActivate activatePackage(objectID);
|
MWMechanics::AiActivate activatePackage(objectID);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(activatePackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(activatePackage, ptr);
|
||||||
std::cout << "AiActivate" << std::endl;
|
Log(Debug::Info) << "AiActivate";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ namespace MWScript
|
||||||
MWMechanics::AiTravel travelPackage(x, y, z);
|
MWMechanics::AiTravel travelPackage(x, y, z);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(travelPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(travelPackage, ptr);
|
||||||
|
|
||||||
std::cout << "AiTravel: " << x << ", " << y << ", " << z << std::endl;
|
Log(Debug::Info) << "AiTravel: " << x << ", " << y << ", " << z;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,8 +127,7 @@ namespace MWScript
|
||||||
MWMechanics::AiEscort escortPackage(actorID, static_cast<int>(duration), x, y, z);
|
MWMechanics::AiEscort escortPackage(actorID, static_cast<int>(duration), x, y, z);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr);
|
||||||
|
|
||||||
std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration
|
Log(Debug::Info) << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,8 +169,7 @@ namespace MWScript
|
||||||
MWMechanics::AiEscort escortPackage(actorID, cellID, static_cast<int>(duration), x, y, z);
|
MWMechanics::AiEscort escortPackage(actorID, cellID, static_cast<int>(duration), x, y, z);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(escortPackage, ptr);
|
||||||
|
|
||||||
std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration
|
Log(Debug::Info) << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -349,8 +348,7 @@ namespace MWScript
|
||||||
MWMechanics::AiFollow followPackage(actorID, duration, x, y ,z);
|
MWMechanics::AiFollow followPackage(actorID, duration, x, y ,z);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(followPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(followPackage, ptr);
|
||||||
|
|
||||||
std::cout << "AiFollow: " << actorID << ", " << x << ", " << y << ", " << z << ", " << duration
|
Log(Debug::Info) << "AiFollow: " << actorID << ", " << x << ", " << y << ", " << z << ", " << duration;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -407,8 +405,7 @@ namespace MWScript
|
||||||
|
|
||||||
MWMechanics::AiFollow followPackage(actorID, cellID, duration, x, y ,z);
|
MWMechanics::AiFollow followPackage(actorID, cellID, duration, x, y ,z);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(followPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(followPackage, ptr);
|
||||||
std::cout << "AiFollow: " << actorID << ", " << x << ", " << y << ", " << z << ", " << duration
|
Log(Debug::Info) << "AiFollow: " << actorID << ", " << x << ", " << y << ", " << z << ", " << duration;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/compiler/extensions.hpp>
|
#include <components/compiler/extensions.hpp>
|
||||||
#include <components/compiler/opcodes.hpp>
|
#include <components/compiler/opcodes.hpp>
|
||||||
|
|
||||||
|
@ -300,8 +302,9 @@ namespace MWScript
|
||||||
if (it == invStore.end())
|
if (it == invStore.end())
|
||||||
{
|
{
|
||||||
it = ptr.getClass().getContainerStore (ptr).add (item, 1, ptr);
|
it = ptr.getClass().getContainerStore (ptr).add (item, 1, ptr);
|
||||||
std::cerr << "Implicitly adding one " << item << " to container "
|
Log(Debug::Warning) << "Implicitly adding one " << item <<
|
||||||
"to fulfil requirements of Equip instruction" << std::endl;
|
" to the inventory store of " << ptr.getCellRef().getRefId() <<
|
||||||
|
" to fulfill the requirements of Equip instruction";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr == MWMechanics::getPlayer())
|
if (ptr == MWMechanics::getPlayer())
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "dialogueextensions.hpp"
|
#include "dialogueextensions.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -16,7 +14,7 @@
|
||||||
|
|
||||||
#include <components/compiler/extensions.hpp>
|
#include <components/compiler/extensions.hpp>
|
||||||
#include <components/compiler/opcodes.hpp>
|
#include <components/compiler/opcodes.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/interpreter/interpreter.hpp>
|
#include <components/interpreter/interpreter.hpp>
|
||||||
#include <components/interpreter/runtime.hpp>
|
#include <components/interpreter/runtime.hpp>
|
||||||
#include <components/interpreter/opcodes.hpp>
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
@ -189,7 +187,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
const std::string error = "Warning: \"forcegreeting\" command works only for actors.";
|
const std::string error = "Warning: \"forcegreeting\" command works only for actors.";
|
||||||
runtime.getContext().report(error);
|
runtime.getContext().report(error);
|
||||||
std::cerr << error << std::endl;
|
Log(Debug::Warning) << error;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "globalscripts.hpp"
|
#include "globalscripts.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/globalscript.hpp>
|
#include <components/esm/globalscript.hpp>
|
||||||
|
@ -125,9 +125,9 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Error)
|
||||||
<< "Failed to add start script " << *iter << " because an exception has "
|
<< "Failed to add start script " << *iter << " because an exception has "
|
||||||
<< "been thrown: " << exception.what() << std::endl;
|
<< "been thrown: " << exception.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,10 +181,9 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Error)
|
||||||
<< "Failed to add start script " << script.mId
|
<< "Failed to add start script " << script.mId
|
||||||
<< " because an exception has been thrown: " << exception.what()
|
<< " because an exception has been thrown: " << exception.what();
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <components/esm/loadscpt.hpp>
|
#include <components/esm/loadscpt.hpp>
|
||||||
#include <components/esm/variant.hpp>
|
#include <components/esm/variant.hpp>
|
||||||
#include <components/esm/locals.hpp>
|
#include <components/esm/locals.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/compiler/locals.hpp>
|
#include <components/compiler/locals.hpp>
|
||||||
#include <components/compiler/exception.hpp>
|
#include <components/compiler/exception.hpp>
|
||||||
|
|
||||||
|
@ -229,10 +229,10 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to read local variable state for script '"
|
Log(Debug::Error) << "Failed to read local variable state for script '"
|
||||||
<< script << "' (legacy format): " << e.what()
|
<< script << "' (legacy format): " << e.what()
|
||||||
<< "\nNum shorts: " << numshorts << " / " << mShorts.size()
|
<< "\nNum shorts: " << numshorts << " / " << mShorts.size()
|
||||||
<< " Num longs: " << numlongs << " / " << mLongs.size() << std::endl;
|
<< " Num longs: " << numlongs << " / " << mLongs.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1201,6 +1201,7 @@ namespace MWScript
|
||||||
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false);
|
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false);
|
||||||
|
|
||||||
MWMechanics::CastSpell cast(ptr, target, false, true);
|
MWMechanics::CastSpell cast(ptr, target, false, true);
|
||||||
|
cast.playSpellCastingEffects(spell->mId);
|
||||||
cast.mHitPosition = target.getRefData().getPosition().asVec3();
|
cast.mHitPosition = target.getRefData().getPosition().asVec3();
|
||||||
cast.mAlwaysSucceed = true;
|
cast.mAlwaysSucceed = true;
|
||||||
cast.cast(spell);
|
cast.cast(spell);
|
||||||
|
@ -1274,8 +1275,7 @@ namespace MWScript
|
||||||
|
|
||||||
virtual void execute (Interpreter::Runtime &runtime)
|
virtual void execute (Interpreter::Runtime &runtime)
|
||||||
{
|
{
|
||||||
/// \todo implement traveling check
|
runtime.push (MWBase::Environment::get().getWorld()->isPlayerTraveling());
|
||||||
runtime.push (0);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "scriptmanagerimp.hpp"
|
#include "scriptmanagerimp.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/loadscpt.hpp>
|
#include <components/esm/loadscpt.hpp>
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -65,14 +66,14 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (const std::exception& error)
|
catch (const std::exception& error)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: An exception has been thrown: " << error.what() << std::endl;
|
Log(Debug::Error) << "Error: An exception has been thrown: " << error.what();
|
||||||
Success = false;
|
Success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Success)
|
if (!Success)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "Warning: compiling failed: " << name << std::endl;
|
<< "Warning: compiling failed: " << name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Success)
|
if (Success)
|
||||||
|
@ -121,8 +122,8 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Execution of script " << name << " failed:" << std::endl;
|
Log(Debug::Error) << "Execution of script " << name << " failed:";
|
||||||
std::cerr << e.what() << std::endl;
|
Log(Debug::Error) << e.what();
|
||||||
|
|
||||||
iter->second.first.clear(); // don't execute again.
|
iter->second.first.clear(); // don't execute again.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "statsextensions.hpp"
|
#include "statsextensions.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -20,7 +19,7 @@
|
||||||
|
|
||||||
#include <components/compiler/extensions.hpp>
|
#include <components/compiler/extensions.hpp>
|
||||||
#include <components/compiler/opcodes.hpp>
|
#include <components/compiler/opcodes.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/interpreter/interpreter.hpp>
|
#include <components/interpreter/interpreter.hpp>
|
||||||
#include <components/interpreter/runtime.hpp>
|
#include <components/interpreter/runtime.hpp>
|
||||||
#include <components/interpreter/opcodes.hpp>
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
@ -257,9 +256,10 @@ namespace MWScript
|
||||||
|
|
||||||
if (R()(runtime, false, true).isEmpty())
|
if (R()(runtime, false, true).isEmpty())
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "Warning: Compensating for broken script in Morrowind.esm by "
|
<< "Warning: Compensating for broken script in Morrowind.esm by "
|
||||||
<< "ignoring remote access to dagoth_ur_1" << std::endl;
|
<< "ignoring remote access to dagoth_ur_1";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,6 +272,7 @@ namespace MWScript
|
||||||
.getDynamic (mIndex));
|
.getDynamic (mIndex));
|
||||||
|
|
||||||
stat.setModified (diff + stat.getModified(), 0);
|
stat.setModified (diff + stat.getModified(), 0);
|
||||||
|
stat.setCurrentModified (diff + stat.getCurrentModified());
|
||||||
|
|
||||||
stat.setCurrent (diff + current);
|
stat.setCurrent (diff + current);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -376,7 +376,7 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
std::string error = "Warning: PositionCell: unknown interior cell (" + cellID + "), moving to exterior instead";
|
std::string error = "Warning: PositionCell: unknown interior cell (" + cellID + "), moving to exterior instead";
|
||||||
runtime.getContext().report (error);
|
runtime.getContext().report (error);
|
||||||
std::cerr << error << std::endl;
|
Log(Debug::Warning) << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(store)
|
if(store)
|
||||||
|
@ -488,7 +488,7 @@ namespace MWScript
|
||||||
if(!cell)
|
if(!cell)
|
||||||
{
|
{
|
||||||
runtime.getContext().report ("unknown cell (" + cellID + ")");
|
runtime.getContext().report ("unknown cell (" + cellID + ")");
|
||||||
std::cerr << "unknown cell (" << cellID << ")\n";
|
Log(Debug::Error) << "Error: unknown cell (" << cellID << ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(store)
|
if(store)
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
|
@ -28,7 +28,7 @@ int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size)
|
||||||
|
|
||||||
int FFmpeg_Decoder::writePacket(void *, uint8_t *, int)
|
int FFmpeg_Decoder::writePacket(void *, uint8_t *, int)
|
||||||
{
|
{
|
||||||
std::cerr<< "can't write to read-only stream" <<std::endl;
|
Log(Debug::Error) << "can't write to read-only stream";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
||||||
char str[1024];
|
char str[1024];
|
||||||
av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels,
|
av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels,
|
||||||
(*mStream)->codec->channel_layout);
|
(*mStream)->codec->channel_layout);
|
||||||
std::cerr<< "Unsupported channel layout: "<<str <<std::endl;
|
Log(Debug::Error) << "Unsupported channel layout: "<< str;
|
||||||
|
|
||||||
if((*mStream)->codec->channels == 1)
|
if((*mStream)->codec->channels == 1)
|
||||||
{
|
{
|
||||||
|
@ -385,7 +385,7 @@ size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
if(!mStream)
|
if(!mStream)
|
||||||
{
|
{
|
||||||
std::cerr<< "No audio stream" <<std::endl;
|
Log(Debug::Error) << "No audio stream";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return readAVAudioData(buffer, bytes);
|
return readAVAudioData(buffer, bytes);
|
||||||
|
@ -395,7 +395,7 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
||||||
{
|
{
|
||||||
if(!mStream)
|
if(!mStream)
|
||||||
{
|
{
|
||||||
std::cerr<< "No audio stream" <<std::endl;
|
Log(Debug::Error) << "No audio stream";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -8,6 +7,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include <OpenThreads/Thread>
|
#include <OpenThreads/Thread>
|
||||||
|
@ -44,8 +44,7 @@ ALCenum checkALCError(ALCdevice *device, const char *func, int line)
|
||||||
{
|
{
|
||||||
ALCenum err = alcGetError(device);
|
ALCenum err = alcGetError(device);
|
||||||
if(err != ALC_NO_ERROR)
|
if(err != ALC_NO_ERROR)
|
||||||
std::cerr<< ">>>>>>>>> ALC error "<<alcGetString(device, err)<<" ("<<err<<") @ "<<
|
Log(Debug::Error) << "ALC error "<< alcGetString(device, err) << " (" << err << ") @ " << func << ":" << line;
|
||||||
func<<":"<<line <<std::endl;
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#define getALCError(d) checkALCError((d), __FUNCTION__, __LINE__)
|
#define getALCError(d) checkALCError((d), __FUNCTION__, __LINE__)
|
||||||
|
@ -54,8 +53,7 @@ ALenum checkALError(const char *func, int line)
|
||||||
{
|
{
|
||||||
ALenum err = alGetError();
|
ALenum err = alGetError();
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
std::cerr<< ">>>>>>>>> AL error "<<alGetString(err)<<" ("<<err<<") @ "<<
|
Log(Debug::Error) << "AL error " << alGetString(err) << " (" << err << ") @ " << func << ":" << line;
|
||||||
func<<":"<<line <<std::endl;
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#define getALError() checkALError(__FUNCTION__, __LINE__)
|
#define getALError() checkALError(__FUNCTION__, __LINE__)
|
||||||
|
@ -256,8 +254,7 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr<< "Unsupported sound format ("<<getChannelConfigName(chans)<<", "<<
|
Log(Debug::Warning) << "Unsupported sound format (" << getChannelConfigName(chans) << ", " << getSampleTypeName(type) << ")";
|
||||||
getSampleTypeName(type)<<")" <<std::endl;
|
|
||||||
return AL_NONE;
|
return AL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,8 +412,9 @@ bool OpenAL_SoundStream::init(bool getLoudnessData)
|
||||||
mDecoder->getInfo(&mSampleRate, &chans, &type);
|
mDecoder->getInfo(&mSampleRate, &chans, &type);
|
||||||
mFormat = getALFormat(chans, type);
|
mFormat = getALFormat(chans, type);
|
||||||
}
|
}
|
||||||
catch(std::exception &e) {
|
catch(std::exception &e)
|
||||||
std::cerr<< "Failed to get stream info: "<<e.what() <<std::endl;
|
{
|
||||||
|
Log(Debug::Error) << "Failed to get stream info: " << e.what();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +520,7 @@ bool OpenAL_SoundStream::process()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception&) {
|
catch(std::exception&) {
|
||||||
std::cout<< "Error updating stream \""<<mDecoder->getName()<<"\"" <<std::endl;
|
Log(Debug::Error) << "Error updating stream \"" << mDecoder->getName() << "\"";
|
||||||
mIsFinished = true;
|
mIsFinished = true;
|
||||||
}
|
}
|
||||||
return !mIsFinished;
|
return !mIsFinished;
|
||||||
|
@ -593,17 +591,18 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
{
|
{
|
||||||
deinit();
|
deinit();
|
||||||
|
|
||||||
std::cout<< "Initializing OpenAL..." <<std::endl;
|
Log(Debug::Info) << "Initializing OpenAL...";
|
||||||
|
|
||||||
mDevice = alcOpenDevice(devname.c_str());
|
mDevice = alcOpenDevice(devname.c_str());
|
||||||
if(!mDevice && !devname.empty())
|
if(!mDevice && !devname.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "Failed to open \""<<devname<<"\", trying default" <<std::endl;
|
Log(Debug::Warning) << "Failed to open \"" << devname << "\", trying default";
|
||||||
mDevice = alcOpenDevice(nullptr);
|
mDevice = alcOpenDevice(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mDevice)
|
if(!mDevice)
|
||||||
{
|
{
|
||||||
std::cerr<< "Failed to open default audio device" <<std::endl;
|
Log(Debug::Error) << "Failed to open default audio device";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,13 +611,13 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
name = alcGetString(mDevice, ALC_ALL_DEVICES_SPECIFIER);
|
name = alcGetString(mDevice, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
if(alcGetError(mDevice) != AL_NO_ERROR || !name)
|
if(alcGetError(mDevice) != AL_NO_ERROR || !name)
|
||||||
name = alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
|
name = alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
|
||||||
std::cout<< "Opened \""<<name<<"\"" <<std::endl;
|
Log(Debug::Info) << "Opened \"" << name << "\"";
|
||||||
|
|
||||||
ALCint major=0, minor=0;
|
ALCint major=0, minor=0;
|
||||||
alcGetIntegerv(mDevice, ALC_MAJOR_VERSION, 1, &major);
|
alcGetIntegerv(mDevice, ALC_MAJOR_VERSION, 1, &major);
|
||||||
alcGetIntegerv(mDevice, ALC_MINOR_VERSION, 1, &minor);
|
alcGetIntegerv(mDevice, ALC_MINOR_VERSION, 1, &minor);
|
||||||
std::cout<< " ALC Version: "<<major<<"."<<minor<<"\n"<<
|
Log(Debug::Info) << " ALC Version: " << major << "." << minor <<"\n" <<
|
||||||
" ALC Extensions: "<<alcGetString(mDevice, ALC_EXTENSIONS) <<std::endl;
|
" ALC Extensions: " << alcGetString(mDevice, ALC_EXTENSIONS);
|
||||||
|
|
||||||
ALC.EXT_EFX = alcIsExtensionPresent(mDevice, "ALC_EXT_EFX");
|
ALC.EXT_EFX = alcIsExtensionPresent(mDevice, "ALC_EXT_EFX");
|
||||||
ALC.SOFT_HRTF = alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF");
|
ALC.SOFT_HRTF = alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF");
|
||||||
|
@ -650,7 +649,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index < 0)
|
if(index < 0)
|
||||||
std::cerr<< "Failed to find HRTF \""<<hrtfname<<"\", using default" <<std::endl;
|
Log(Debug::Warning) << "Failed to find HRTF \"" << hrtfname << "\", using default";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attrs.push_back(ALC_HRTF_ID_SOFT);
|
attrs.push_back(ALC_HRTF_ID_SOFT);
|
||||||
|
@ -663,7 +662,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
mContext = alcCreateContext(mDevice, attrs.data());
|
mContext = alcCreateContext(mDevice, attrs.data());
|
||||||
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
||||||
{
|
{
|
||||||
std::cerr<< "Failed to setup audio context: "<<alcGetString(mDevice, alcGetError(mDevice)) <<std::endl;
|
Log(Debug::Error) << "Failed to setup audio context: "<<alcGetString(mDevice, alcGetError(mDevice));
|
||||||
if(mContext)
|
if(mContext)
|
||||||
alcDestroyContext(mContext);
|
alcDestroyContext(mContext);
|
||||||
mContext = nullptr;
|
mContext = nullptr;
|
||||||
|
@ -672,23 +671,23 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout<< " Vendor: "<<alGetString(AL_VENDOR)<<"\n"<<
|
Log(Debug::Info) << " Vendor: "<<alGetString(AL_VENDOR)<<"\n"<<
|
||||||
" Renderer: "<<alGetString(AL_RENDERER)<<"\n"<<
|
" Renderer: "<<alGetString(AL_RENDERER)<<"\n"<<
|
||||||
" Version: "<<alGetString(AL_VERSION)<<"\n"<<
|
" Version: "<<alGetString(AL_VERSION)<<"\n"<<
|
||||||
" Extensions: "<<alGetString(AL_EXTENSIONS)<<std::endl;
|
" Extensions: "<<alGetString(AL_EXTENSIONS);
|
||||||
|
|
||||||
if(!ALC.SOFT_HRTF)
|
if(!ALC.SOFT_HRTF)
|
||||||
std::cout<< "HRTF status unavailable" <<std::endl;
|
Log(Debug::Warning) << "HRTF status unavailable";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALCint hrtf_state;
|
ALCint hrtf_state;
|
||||||
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
||||||
if(!hrtf_state)
|
if(!hrtf_state)
|
||||||
std::cout<< "HRTF disabled" <<std::endl;
|
Log(Debug::Info) << "HRTF disabled";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ALCchar *hrtf = alcGetString(mDevice, ALC_HRTF_SPECIFIER_SOFT);
|
const ALCchar *hrtf = alcGetString(mDevice, ALC_HRTF_SPECIFIER_SOFT);
|
||||||
std::cout<< "Enabled HRTF "<<hrtf <<std::endl;
|
Log(Debug::Info) << "Enabled HRTF " << hrtf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +715,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
}
|
}
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "Could not allocate any sound sources" <<std::endl;
|
Log(Debug::Warning) << "Could not allocate any sound sourcess";
|
||||||
alcMakeContextCurrent(nullptr);
|
alcMakeContextCurrent(nullptr);
|
||||||
alcDestroyContext(mContext);
|
alcDestroyContext(mContext);
|
||||||
mContext = nullptr;
|
mContext = nullptr;
|
||||||
|
@ -724,7 +723,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
mDevice = nullptr;
|
mDevice = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::cout<< "Allocated "<<mFreeSources.size()<<" sound sources" <<std::endl;
|
Log(Debug::Info) << "Allocated " << mFreeSources.size() << " sound sources";
|
||||||
|
|
||||||
if(ALC.EXT_EFX)
|
if(ALC.EXT_EFX)
|
||||||
{
|
{
|
||||||
|
@ -775,7 +774,7 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
alFilteri(mWaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
alFilteri(mWaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
||||||
if(alGetError() == AL_NO_ERROR)
|
if(alGetError() == AL_NO_ERROR)
|
||||||
{
|
{
|
||||||
std::cout<< "Low-pass filter supported" <<std::endl;
|
Log(Debug::Info) << "Low-pass filter supported";
|
||||||
alFilterf(mWaterFilter, AL_LOWPASS_GAIN, 0.9f);
|
alFilterf(mWaterFilter, AL_LOWPASS_GAIN, 0.9f);
|
||||||
alFilterf(mWaterFilter, AL_LOWPASS_GAINHF, 0.125f);
|
alFilterf(mWaterFilter, AL_LOWPASS_GAINHF, 0.125f);
|
||||||
}
|
}
|
||||||
|
@ -795,12 +794,12 @@ bool OpenAL_Output::init(const std::string &devname, const std::string &hrtfname
|
||||||
{
|
{
|
||||||
alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
|
alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
|
||||||
if(alGetError() == AL_NO_ERROR)
|
if(alGetError() == AL_NO_ERROR)
|
||||||
std::cout<< "EAX Reverb supported" <<std::endl;
|
Log(Debug::Info) << "EAX Reverb supported";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
|
alEffecti(mDefaultEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
|
||||||
if(alGetError() == AL_NO_ERROR)
|
if(alGetError() == AL_NO_ERROR)
|
||||||
std::cout<< "Standard Reverb supported" <<std::endl;
|
Log(Debug::Info) << "Standard Reverb supported";
|
||||||
}
|
}
|
||||||
EFXEAXREVERBPROPERTIES props = EFX_REVERB_PRESET_GENERIC;
|
EFXEAXREVERBPROPERTIES props = EFX_REVERB_PRESET_GENERIC;
|
||||||
props.flGain = 0.0f;
|
props.flGain = 0.0f;
|
||||||
|
@ -891,7 +890,7 @@ void OpenAL_Output::setHrtf(const std::string &hrtfname, HrtfMode hrtfmode)
|
||||||
{
|
{
|
||||||
if(!mDevice || !ALC.SOFT_HRTF)
|
if(!mDevice || !ALC.SOFT_HRTF)
|
||||||
{
|
{
|
||||||
std::cerr<< "HRTF extension not present" <<std::endl;
|
Log(Debug::Info) << "HRTF extension not present";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,7 +923,7 @@ void OpenAL_Output::setHrtf(const std::string &hrtfname, HrtfMode hrtfmode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index < 0)
|
if(index < 0)
|
||||||
std::cerr<< "Failed to find HRTF name \""<<hrtfname<<"\", using default" <<std::endl;
|
Log(Debug::Warning) << "Failed to find HRTF name \"" << hrtfname << "\", using default";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attrs.push_back(ALC_HRTF_ID_SOFT);
|
attrs.push_back(ALC_HRTF_ID_SOFT);
|
||||||
|
@ -937,11 +936,11 @@ void OpenAL_Output::setHrtf(const std::string &hrtfname, HrtfMode hrtfmode)
|
||||||
ALCint hrtf_state;
|
ALCint hrtf_state;
|
||||||
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
||||||
if(!hrtf_state)
|
if(!hrtf_state)
|
||||||
std::cout<< "HRTF disabled" <<std::endl;
|
Log(Debug::Info) << "HRTF disabled";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ALCchar *hrtf = alcGetString(mDevice, ALC_HRTF_SPECIFIER_SOFT);
|
const ALCchar *hrtf = alcGetString(mDevice, ALC_HRTF_SPECIFIER_SOFT);
|
||||||
std::cout<< "Enabled HRTF "<<hrtf <<std::endl;
|
Log(Debug::Info) << "Enabled HRTF " << hrtf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,7 +976,7 @@ std::pair<Sound_Handle,size_t> OpenAL_Output::loadSound(const std::string &fname
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
std::cerr<< "Failed to load audio from "<<fname<<": "<<e.what() <<std::endl;
|
Log(Debug::Error) << "Failed to load audio from " << fname << ": " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.empty())
|
if(data.empty())
|
||||||
|
@ -1139,7 +1138,7 @@ bool OpenAL_Output::playSound(Sound *sound, Sound_Handle data, float offset)
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "No free sources!" <<std::endl;
|
Log(Debug::Warning) << "No free sources!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
source = mFreeSources.front();
|
source = mFreeSources.front();
|
||||||
|
@ -1168,7 +1167,7 @@ bool OpenAL_Output::playSound3D(Sound *sound, Sound_Handle data, float offset)
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "No free sources!" <<std::endl;
|
Log(Debug::Warning) << "No free sources!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
source = mFreeSources.front();
|
source = mFreeSources.front();
|
||||||
|
@ -1236,13 +1235,14 @@ bool OpenAL_Output::streamSound(DecoderPtr decoder, Stream *sound)
|
||||||
{
|
{
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "No free sources!" <<std::endl;
|
Log(Debug::Warning) << "No free sources!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ALuint source = mFreeSources.front();
|
ALuint source = mFreeSources.front();
|
||||||
|
|
||||||
if(sound->getIsLooping())
|
if(sound->getIsLooping())
|
||||||
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\"";
|
||||||
|
|
||||||
initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
|
initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
|
||||||
false, sound->getUseEnv());
|
false, sound->getUseEnv());
|
||||||
if(getALError() != AL_NO_ERROR)
|
if(getALError() != AL_NO_ERROR)
|
||||||
|
@ -1266,13 +1266,14 @@ bool OpenAL_Output::streamSound3D(DecoderPtr decoder, Stream *sound, bool getLou
|
||||||
{
|
{
|
||||||
if(mFreeSources.empty())
|
if(mFreeSources.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "No free sources!" <<std::endl;
|
Log(Debug::Warning) << "No free sources!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ALuint source = mFreeSources.front();
|
ALuint source = mFreeSources.front();
|
||||||
|
|
||||||
if(sound->getIsLooping())
|
if(sound->getIsLooping())
|
||||||
std::cout <<"Warning: cannot loop stream \""<<decoder->getName()<<"\""<< std::endl;
|
Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\"";
|
||||||
|
|
||||||
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
|
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
|
||||||
sound->getRealVolume(), sound->getPitch(), false, sound->getUseEnv());
|
sound->getRealVolume(), sound->getPitch(), false, sound->getUseEnv());
|
||||||
if(getALError() != AL_NO_ERROR)
|
if(getALError() != AL_NO_ERROR)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "soundmanagerimp.hpp"
|
#include "soundmanagerimp.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
@ -8,7 +7,7 @@
|
||||||
#include <osg/Matrixf>
|
#include <osg/Matrixf>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -81,7 +80,7 @@ namespace MWSound
|
||||||
|
|
||||||
if(!useSound)
|
if(!useSound)
|
||||||
{
|
{
|
||||||
std::cout<< "Sound disabled." <<std::endl;
|
Log(Debug::Info) << "Sound disabled.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,23 +92,28 @@ namespace MWSound
|
||||||
std::string devname = Settings::Manager::getString("device", "Sound");
|
std::string devname = Settings::Manager::getString("device", "Sound");
|
||||||
if(!mOutput->init(devname, hrtfname, hrtfmode))
|
if(!mOutput->init(devname, hrtfname, hrtfmode))
|
||||||
{
|
{
|
||||||
std::cerr<< "Failed to initialize audio output, sound disabled" <<std::endl;
|
Log(Debug::Error) << "Failed to initialize audio output, sound disabled";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> names = mOutput->enumerate();
|
std::vector<std::string> names = mOutput->enumerate();
|
||||||
std::cout <<"Enumerated output devices:\n";
|
std::stringstream stream;
|
||||||
|
|
||||||
|
stream << "Enumerated output devices:\n";
|
||||||
for(const std::string &name : names)
|
for(const std::string &name : names)
|
||||||
std::cout <<" "<<name<<"\n";
|
stream << " " << name;
|
||||||
std::cout.flush();
|
|
||||||
|
Log(Debug::Info) << stream.str();
|
||||||
|
stream.str("");
|
||||||
|
|
||||||
names = mOutput->enumerateHrtf();
|
names = mOutput->enumerateHrtf();
|
||||||
if(!names.empty())
|
if(!names.empty())
|
||||||
{
|
{
|
||||||
std::cout<< "Enumerated HRTF names:\n";
|
stream << "Enumerated HRTF names:\n";
|
||||||
for(const std::string &name : names)
|
for(const std::string &name : names)
|
||||||
std::cout <<" "<<name<<"\n";
|
stream << " " << name;
|
||||||
std::cout.flush();
|
|
||||||
|
Log(Debug::Info) << stream.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +225,7 @@ namespace MWSound
|
||||||
do {
|
do {
|
||||||
if(mUnusedBuffers.empty())
|
if(mUnusedBuffers.empty())
|
||||||
{
|
{
|
||||||
std::cerr<< "No unused sound buffers to free, using "<<mBufferCacheSize<<" bytes!" <<std::endl;
|
Log(Debug::Warning) << "No unused sound buffers to free, using " << mBufferCacheSize << " bytes!";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Sound_Buffer *unused = mUnusedBuffers.back();
|
Sound_Buffer *unused = mUnusedBuffers.back();
|
||||||
|
@ -360,7 +364,7 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
if(!mOutput->isInitialized())
|
if(!mOutput->isInitialized())
|
||||||
return;
|
return;
|
||||||
std::cout <<"Playing "<<filename<< std::endl;
|
Log(Debug::Info) << "Playing " << filename;
|
||||||
mLastPlayedMusic = filename;
|
mLastPlayedMusic = filename;
|
||||||
|
|
||||||
stopMusic();
|
stopMusic();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "statemanagerimp.hpp"
|
#include "statemanagerimp.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/cellid.hpp>
|
#include <components/esm/cellid.hpp>
|
||||||
|
@ -157,7 +159,7 @@ void MWState::StateManager::newGame (bool bypass)
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
error << "Failed to start new game: " << e.what();
|
error << "Failed to start new game: " << e.what();
|
||||||
|
|
||||||
std::cerr << error.str() << std::endl;
|
Log(Debug::Error) << error.str();
|
||||||
cleanup (true);
|
cleanup (true);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||||
|
@ -283,7 +285,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
|
|
||||||
// Ensure we have written the number of records that was estimated
|
// Ensure we have written the number of records that was estimated
|
||||||
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
|
if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
|
||||||
std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;
|
Log(Debug::Warning) << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount();
|
||||||
|
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
@ -305,7 +307,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
error << "Failed to save game: " << e.what();
|
error << "Failed to save game: " << e.what();
|
||||||
|
|
||||||
std::cerr << error.str() << std::endl;
|
Log(Debug::Error) << error.str();
|
||||||
|
|
||||||
std::vector<std::string> buttons;
|
std::vector<std::string> buttons;
|
||||||
buttons.push_back("#{sOk}");
|
buttons.push_back("#{sOk}");
|
||||||
|
@ -483,7 +485,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
default:
|
default:
|
||||||
|
|
||||||
// ignore invalid records
|
// ignore invalid records
|
||||||
std::cerr << "Warning: Ignoring unknown record: " << n.toString() << std::endl;
|
Log(Debug::Warning) << "Warning: Ignoring unknown record: " << n.toString();
|
||||||
reader.skipRecord();
|
reader.skipRecord();
|
||||||
}
|
}
|
||||||
int progressPercent = static_cast<int>(float(reader.getFileOffset())/total*100);
|
int progressPercent = static_cast<int>(float(reader.getFileOffset())/total*100);
|
||||||
|
@ -549,7 +551,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
error << "Failed to load saved game: " << e.what();
|
error << "Failed to load saved game: " << e.what();
|
||||||
|
|
||||||
std::cerr << error.str() << std::endl;
|
Log(Debug::Error) << error.str();
|
||||||
cleanup (true);
|
cleanup (true);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
||||||
|
@ -625,7 +627,7 @@ bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const
|
||||||
if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), *it)
|
if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), *it)
|
||||||
== selectedContentFiles.end())
|
== selectedContentFiles.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Savegame dependency " << *it << " is missing." << std::endl;
|
Log(Debug::Warning) << "Warning: Savegame dependency " << *it << " is missing.";
|
||||||
notFound = true;
|
notFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +655,7 @@ void MWState::StateManager::writeScreenshot(std::vector<char> &imageData) const
|
||||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
||||||
if (!readerwriter)
|
if (!readerwriter)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Unable to write screenshot, can't find a jpg ReaderWriter" << std::endl;
|
Log(Debug::Error) << "Error: Unable to write screenshot, can't find a jpg ReaderWriter";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,7 +663,7 @@ void MWState::StateManager::writeScreenshot(std::vector<char> &imageData) const
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*screenshot, ostream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*screenshot, ostream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: Unable to write screenshot: " << result.message() << " code " << result.status() << std::endl;
|
Log(Debug::Error) << "Error: Unable to write screenshot: " << result.message() << " code " << result.status();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "cellpreloader.hpp"
|
#include "cellpreloader.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
|
@ -229,12 +228,12 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (!mWorkQueue)
|
if (!mWorkQueue)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: can't preload, no work queue set " << std::endl;
|
Log(Debug::Error) << "Error: can't preload, no work queue set";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cell->getState() == CellStore::State_Unloaded)
|
if (cell->getState() == CellStore::State_Unloaded)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: can't preload objects for unloaded cell" << std::endl;
|
Log(Debug::Error) << "Error: can't preload objects for unloaded cell";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "cells.hpp"
|
#include "cells.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
|
@ -350,7 +349,7 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
// silently drop cells that don't exist anymore
|
// silently drop cells that don't exist anymore
|
||||||
std::cerr << "Warning: Dropping state for cell " << state.mId.mWorldspace << " (cell no longer exists)" << std::endl;
|
Log(Debug::Warning) << "Warning: Dropping state for cell " << state.mId.mWorldspace << " (cell no longer exists)";
|
||||||
reader.skipRecord();
|
reader.skipRecord();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
#include "cellstore.hpp"
|
#include "cellstore.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -18,6 +15,8 @@
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/cellstate.hpp>
|
#include <components/esm/cellstate.hpp>
|
||||||
#include <components/esm/cellid.hpp>
|
#include <components/esm/cellid.hpp>
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
@ -153,7 +152,7 @@ namespace
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Warning: Dropping reference to " << state.mRef.mRefID << " (invalid content file link)" << std::endl;
|
Log(Debug::Warning) << "Warning: Dropping reference to " << state.mRef.mRefID << " (invalid content file link)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,9 +210,9 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "Warning: could not resolve cell reference '" << ref.mRefID << "'"
|
<< "Warning: could not resolve cell reference '" << ref.mRefID << "'"
|
||||||
<< " (dropping reference)" << std::endl;
|
<< " (dropping reference)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +684,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "An error occurred listing references for cell " << getCell()->getDescription() << ": " << e.what() << std::endl;
|
Log(Debug::Error) << "An error occurred listing references for cell " << getCell()->getDescription() << ": " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +740,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "An error occurred loading references for cell " << getCell()->getDescription() << ": " << e.what() << std::endl;
|
Log(Debug::Error) << "An error occurred loading references for cell " << getCell()->getDescription() << ": " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,11 +846,10 @@ namespace MWWorld
|
||||||
case ESM::REC_WEAP: mWeapons.load(ref, deleted, store); break;
|
case ESM::REC_WEAP: mWeapons.load(ref, deleted, store); break;
|
||||||
case ESM::REC_BODY: mBodyParts.load(ref, deleted, store); break;
|
case ESM::REC_BODY: mBodyParts.load(ref, deleted, store); break;
|
||||||
|
|
||||||
case 0: std::cerr << "Cell reference '" + ref.mRefID + "' not found!\n"; return;
|
case 0: Log(Debug::Error) << "Cell reference '" + ref.mRefID + "' not found!"; return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
std::cerr
|
Log(Debug::Error) << "Error: Ignoring reference '" << ref.mRefID << "' of unhandled type";
|
||||||
<< "Error: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +942,7 @@ namespace MWWorld
|
||||||
int type = MWBase::Environment::get().getWorld()->getStore().find(cref.mRefID);
|
int type = MWBase::Environment::get().getWorld()->getStore().find(cref.mRefID);
|
||||||
if (type == 0)
|
if (type == 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Dropping reference to '" << cref.mRefID << "' (object no longer exists)" << std::endl;
|
Log(Debug::Warning) << "Dropping reference to '" << cref.mRefID << "' (object no longer exists)";
|
||||||
reader.skipHSubUntil("OBJE");
|
reader.skipHSubUntil("OBJE");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1080,7 +1078,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (!visitor.mFound)
|
if (!visitor.mFound)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Dropping moved ref tag for " << refnum.mIndex << " (moved object no longer exists)" << std::endl;
|
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex << " (moved object no longer exists)";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,8 +1088,8 @@ namespace MWWorld
|
||||||
|
|
||||||
if (otherCell == NULL)
|
if (otherCell == NULL)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Dropping moved ref tag for " << movedRef->mRef.getRefId()
|
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << movedRef->mRef.getRefId()
|
||||||
<< " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location." << std::endl;
|
<< " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location.";
|
||||||
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
|
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
|
||||||
// Restore original coordinates:
|
// Restore original coordinates:
|
||||||
movedRef->mData.setPosition(movedRef->mRef.getPosition());
|
movedRef->mData.setPosition(movedRef->mRef.getPosition());
|
||||||
|
@ -1101,7 +1099,7 @@ namespace MWWorld
|
||||||
if (otherCell == this)
|
if (otherCell == this)
|
||||||
{
|
{
|
||||||
// Should never happen unless someone's tampering with files.
|
// Should never happen unless someone's tampering with files.
|
||||||
std::cerr << "Found invalid moved ref, ignoring" << std::endl;
|
Log(Debug::Warning) << "Found invalid moved ref, ignoring";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/inventorystate.hpp>
|
#include <components/esm/inventorystate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -596,7 +597,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: MWWorld::ContainerStore::addInitialItem: " << e.what() << std::endl;
|
Log(Debug::Warning) << "Warning: MWWorld::ContainerStore::addInitialItem: " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -920,10 +921,10 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory)
|
||||||
case ESM::REC_WEAP: readEquipmentState (getState (weapons, state), thisIndex, inventory); break;
|
case ESM::REC_WEAP: readEquipmentState (getState (weapons, state), thisIndex, inventory); break;
|
||||||
case ESM::REC_LIGH: readEquipmentState (getState (lights, state), thisIndex, inventory); break;
|
case ESM::REC_LIGH: readEquipmentState (getState (lights, state), thisIndex, inventory); break;
|
||||||
case 0:
|
case 0:
|
||||||
std::cerr << "Dropping inventory reference to '" << state.mRef.mRefID << "' (object no longer exists)" << std::endl;
|
Log(Debug::Warning) << "Dropping inventory reference to '" << state.mRef.mRefID << "' (object no longer exists)";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Warning: Invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl;
|
Log(Debug::Warning) << "Warning: Invalid item type in inventory state, refid " << state.mRef.mRefID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#define CONTENTLOADER_HPP
|
#define CONTENTLOADER_HPP
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <iostream>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <MyGUI_TextIterator.h>
|
#include <MyGUI_TextIterator.h>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include "components/loadinglistener/loadinglistener.hpp"
|
#include "components/loadinglistener/loadinglistener.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -24,8 +24,8 @@ struct ContentLoader
|
||||||
|
|
||||||
virtual void load(const boost::filesystem::path& filepath, int& index)
|
virtual void load(const boost::filesystem::path& filepath, int& index)
|
||||||
{
|
{
|
||||||
std::cout << "Loading content file " << filepath.string() << std::endl;
|
Log(Debug::Info) << "Loading content file " << filepath.string();
|
||||||
mListener.setLabel(MyGUI::TextIterator::toTagsString(filepath.string()));
|
mListener.setLabel(MyGUI::TextIterator::toTagsString(filepath.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#include "esmstore.hpp"
|
#include "esmstore.hpp"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/loadinglistener/loadinglistener.hpp>
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "error: info record without dialog" << std::endl;
|
Log(Debug::Error) << "Error: info record without dialog";
|
||||||
esm.skipRecord();
|
esm.skipRecord();
|
||||||
}
|
}
|
||||||
} else if (n.intval == ESM::REC_MGEF) {
|
} else if (n.intval == ESM::REC_MGEF) {
|
||||||
|
@ -170,7 +169,7 @@ void ESMStore::validate()
|
||||||
const ESM::Faction *fact = mFactions.search(npcFaction);
|
const ESM::Faction *fact = mFactions.search(npcFaction);
|
||||||
if (!fact)
|
if (!fact)
|
||||||
{
|
{
|
||||||
std::cerr << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent faction '" << npc.mFaction << "', ignoring it." << std::endl;
|
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent faction '" << npc.mFaction << "', ignoring it.";
|
||||||
npc.mFaction = "";
|
npc.mFaction = "";
|
||||||
npc.mNpdt.mRank = -1;
|
npc.mNpdt.mRank = -1;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -183,7 +182,7 @@ void ESMStore::validate()
|
||||||
const ESM::Class *cls = mClasses.search(npcClass);
|
const ESM::Class *cls = mClasses.search(npcClass);
|
||||||
if (!cls)
|
if (!cls)
|
||||||
{
|
{
|
||||||
std::cerr << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent class '" << npc.mClass << "', using '" << defaultCls << "' class as replacement." << std::endl;
|
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent class '" << npc.mClass << "', using '" << defaultCls << "' class as replacement.";
|
||||||
npc.mClass = defaultCls;
|
npc.mClass = defaultCls;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/loadench.hpp>
|
#include <components/esm/loadench.hpp>
|
||||||
#include <components/esm/inventorystate.hpp>
|
#include <components/esm/inventorystate.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
@ -932,7 +933,7 @@ void MWWorld::InventoryStore::updateRechargingItems()
|
||||||
enchantmentId);
|
enchantmentId);
|
||||||
if (!enchantment)
|
if (!enchantment)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Can't find enchantment '" << enchantmentId << "' on item " << it->getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Warning: Can't find enchantment '" << enchantmentId << "' on item " << it->getCellRef().getRefId();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "livecellref.hpp"
|
#include "livecellref.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/objectstate.hpp>
|
#include <components/esm/objectstate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -38,10 +37,9 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state)
|
||||||
}
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Error)
|
||||||
<< "Error: failed to load state for local script " << scriptId
|
<< "Error: failed to load state for local script " << scriptId
|
||||||
<< " because an exception has been thrown: " << exception.what()
|
<< " because an exception has been thrown: " << exception.what();
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +49,7 @@ void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state)
|
||||||
|
|
||||||
if (!mRef.getSoul().empty() && !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(mRef.getSoul()))
|
if (!mRef.getSoul().empty() && !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(mRef.getSoul()))
|
||||||
{
|
{
|
||||||
std::cerr << "Soul '" << mRef.getSoul() << "' not found, removing the soul from soul gem" << std::endl;
|
Log(Debug::Warning) << "Soul '" << mRef.getSoul() << "' not found, removing the soul from soul gem";
|
||||||
mRef.setSoul(std::string());
|
mRef.setSoul(std::string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
#include "localscripts.hpp"
|
#include "localscripts.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include "esmstore.hpp"
|
#include "esmstore.hpp"
|
||||||
#include "cellstore.hpp"
|
#include "cellstore.hpp"
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -93,7 +91,7 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr)
|
||||||
for (std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin(); iter!=mScripts.end(); ++iter)
|
for (std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin(); iter!=mScripts.end(); ++iter)
|
||||||
if (iter->second==ptr)
|
if (iter->second==ptr)
|
||||||
{
|
{
|
||||||
std::cerr << "Error: tried to add local script twice for " << ptr.getCellRef().getRefId() << std::endl;
|
Log(Debug::Warning) << "Error: tried to add local script twice for " << ptr.getCellRef().getRefId();
|
||||||
remove(ptr);
|
remove(ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -102,15 +100,15 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr)
|
||||||
}
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
std::cerr
|
Log(Debug::Error)
|
||||||
<< "failed to add local script " << scriptName
|
<< "failed to add local script " << scriptName
|
||||||
<< " because an exception has been thrown: " << exception.what() << std::endl;
|
<< " because an exception has been thrown: " << exception.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cerr
|
Log(Debug::Warning)
|
||||||
<< "failed to add local script " << scriptName
|
<< "failed to add local script " << scriptName
|
||||||
<< " because the script does not exist." << std::endl;
|
<< " because the script does not exist.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::LocalScripts::addCell (CellStore *cell)
|
void MWWorld::LocalScripts::addCell (CellStore *cell)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -399,7 +400,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (!player.mObject.mEnabled)
|
if (!player.mObject.mEnabled)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Savegame attempted to disable the player." << std::endl;
|
Log(Debug::Warning) << "Warning: Savegame attempted to disable the player.";
|
||||||
player.mObject.mEnabled = true;
|
player.mObject.mEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +427,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Player cell '" << player.mCellId.mWorldspace << "' no longer exists" << std::endl;
|
Log(Debug::Warning) << "Warning: Player cell '" << player.mCellId.mWorldspace << "' no longer exists";
|
||||||
// Cell no longer exists. The loader will have to choose a default cell.
|
// Cell no longer exists. The loader will have to choose a default cell.
|
||||||
mCellStore = NULL;
|
mCellStore = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "projectilemanager.hpp"
|
#include "projectilemanager.hpp"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <osg/PositionAttitudeTransform>
|
||||||
#include <osg/ComputeBoundsVisitor>
|
#include <osg/ComputeBoundsVisitor>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/projectilestate.hpp>
|
#include <components/esm/projectilestate.hpp>
|
||||||
|
|
||||||
|
@ -647,7 +648,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Failed to recreate magic projectile from saved data (id \"" << state.mSpellId << "\" no longer exists?)" << std::endl;
|
Log(Debug::Warning) << "Warning: Failed to recreate magic projectile from saved data (id \"" << state.mSpellId << "\" no longer exists?)";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "scene.hpp"
|
#include "scene.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
@ -14,6 +13,7 @@
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/loadinglistener/loadinglistener.hpp>
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
@ -67,7 +67,7 @@ namespace
|
||||||
{
|
{
|
||||||
if (ptr.getRefData().getBaseNode() || physics.getActor(ptr))
|
if (ptr.getRefData().getBaseNode() || physics.getActor(ptr))
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Tried to add " << ptr.getCellRef().getRefId() << " to the scene twice" << std::endl;
|
Log(Debug::Warning) << "Warning: Tried to add " << ptr.getCellRef().getRefId() << " to the scene twice";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ namespace
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::string error ("failed to render '" + ptr.getCellRef().getRefId() + "': ");
|
std::string error ("failed to render '" + ptr.getCellRef().getRefId() + "': ");
|
||||||
std::cerr << error + e.what() << std::endl;
|
Log(Debug::Error) << error + e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
||||||
{
|
{
|
||||||
std::cout << "Unloading cell\n";
|
Log(Debug::Info) << "Unloading cell " << (*iter)->getCell()->getDescription();
|
||||||
ListAndResetObjectsVisitor visitor;
|
ListAndResetObjectsVisitor visitor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -302,7 +302,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if(result.second)
|
if(result.second)
|
||||||
{
|
{
|
||||||
std::cout << "Loading cell " << cell->getCell()->getDescription() << std::endl;
|
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
||||||
|
|
||||||
float verts = ESM::Land::LAND_SIZE;
|
float verts = ESM::Land::LAND_SIZE;
|
||||||
float worldsize = ESM::Land::REAL_SIZE;
|
float worldsize = ESM::Land::REAL_SIZE;
|
||||||
|
@ -614,7 +614,7 @@ namespace MWWorld
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Changing to interior\n";
|
Log(Debug::Info) << "Changing to interior";
|
||||||
|
|
||||||
// unload
|
// unload
|
||||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||||
|
@ -707,7 +707,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "failed to render '" << ptr.getCellRef().getRefId() << "': " << e.what() << std::endl;
|
Log(Debug::Error) << "failed to render '" << ptr.getCellRef().getRefId() << "': " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "store.hpp"
|
#include "store.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
|
@ -8,7 +10,6 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -692,7 +693,7 @@ namespace MWWorld
|
||||||
if (it_lease != wipecell->mLeasedRefs.end())
|
if (it_lease != wipecell->mLeasedRefs.end())
|
||||||
wipecell->mLeasedRefs.erase(it_lease);
|
wipecell->mLeasedRefs.erase(it_lease);
|
||||||
else
|
else
|
||||||
std::cerr << "Error: can't find " << it->mRefNum.mIndex << " " << it->mRefNum.mContentFile << " in leasedRefs " << std::endl;
|
Log(Debug::Error) << "Error: can't find " << it->mRefNum.mIndex << " " << it->mRefNum.mContentFile << " in leasedRefs";
|
||||||
}
|
}
|
||||||
*itold = *it;
|
*itold = *it;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue