forked from teamnwah/openmw-tes3coop
resolve conflict in character.cpp
This commit is contained in:
commit
7002412760
124 changed files with 1820 additions and 870 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,7 +3,6 @@ CMakeFiles
|
||||||
*/CMakeFiles
|
*/CMakeFiles
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
CMakeLists.txt.user
|
|
||||||
Makefile
|
Makefile
|
||||||
makefile
|
makefile
|
||||||
build
|
build
|
||||||
|
@ -22,6 +21,8 @@ Doxygen
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
.directory
|
.directory
|
||||||
|
## qt-creator
|
||||||
|
CMakeLists.txt.user*
|
||||||
|
|
||||||
## resources
|
## resources
|
||||||
data
|
data
|
||||||
|
|
|
@ -15,7 +15,7 @@ before_install:
|
||||||
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
|
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
|
||||||
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
|
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
|
||||||
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
|
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
|
||||||
- sudo apt-get install -qq libbullet-dev libogre-1.8-dev libmygui-dev libsdl2-dev libunshield-dev
|
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
|
||||||
- sudo mkdir /usr/src/gtest/build
|
- sudo mkdir /usr/src/gtest/build
|
||||||
- cd /usr/src/gtest/build
|
- cd /usr/src/gtest/build
|
||||||
- sudo cmake .. -DBUILD_SHARED_LIBS=1
|
- sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||||
|
|
|
@ -99,8 +99,6 @@ set(OENGINE_BULLET
|
||||||
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
||||||
${LIBDIR}/openengine/bullet/BtOgreGP.h
|
${LIBDIR}/openengine/bullet/BtOgreGP.h
|
||||||
${LIBDIR}/openengine/bullet/BtOgrePG.h
|
${LIBDIR}/openengine/bullet/BtOgrePG.h
|
||||||
${LIBDIR}/openengine/bullet/CMotionState.cpp
|
|
||||||
${LIBDIR}/openengine/bullet/CMotionState.h
|
|
||||||
${LIBDIR}/openengine/bullet/physic.cpp
|
${LIBDIR}/openengine/bullet/physic.cpp
|
||||||
${LIBDIR}/openengine/bullet/physic.hpp
|
${LIBDIR}/openengine/bullet/physic.hpp
|
||||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||||
|
@ -212,7 +210,7 @@ if (HAVE_UNORDERED_MAP)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)
|
set(BOOST_COMPONENTS system filesystem program_options)
|
||||||
|
|
||||||
IF(BOOST_STATIC)
|
IF(BOOST_STATIC)
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
|
|
@ -137,8 +137,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
||||||
target_link_libraries(omwlauncher gcov)
|
target_link_libraries(omwlauncher gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
target_link_libraries(omwlauncher dl Xt)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ if(WIN32)
|
||||||
set(QT_USE_QTMAIN TRUE)
|
set(QT_USE_QTMAIN TRUE)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtXml QtXmlPatterns REQUIRED)
|
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||||
include(${QT_USE_FILE})
|
include(${QT_USE_FILE})
|
||||||
|
|
||||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||||
|
|
|
@ -74,6 +74,7 @@ add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||||
|
disease
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwbase
|
add_openmw_dir (mwbase
|
||||||
|
@ -82,6 +83,8 @@ add_openmw_dir (mwbase
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||||
|
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||||
|
|
||||||
IF(OGRE_STATIC)
|
IF(OGRE_STATIC)
|
||||||
ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
|
ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
|
||||||
|
@ -111,6 +114,7 @@ add_definitions(${SOUND_DEFINE})
|
||||||
target_link_libraries(openmw
|
target_link_libraries(openmw
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
${OGRE_STATIC_PLUGINS}
|
${OGRE_STATIC_PLUGINS}
|
||||||
|
${SHINY_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
${SOUND_INPUT_LIBRARY}
|
${SOUND_INPUT_LIBRARY}
|
||||||
|
@ -118,7 +122,6 @@ target_link_libraries(openmw
|
||||||
${MYGUI_LIBRARIES}
|
${MYGUI_LIBRARIES}
|
||||||
${SDL2_LIBRARY}
|
${SDL2_LIBRARY}
|
||||||
${MYGUI_PLATFORM_LIBRARIES}
|
${MYGUI_PLATFORM_LIBRARIES}
|
||||||
${SHINY_LIBRARIES}
|
|
||||||
"oics"
|
"oics"
|
||||||
"sdl4ogre"
|
"sdl4ogre"
|
||||||
components
|
components
|
||||||
|
@ -137,12 +140,6 @@ if (UNIX AND NOT APPLE)
|
||||||
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
target_link_libraries(openmw dl Xt)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(COCOA_FRAMEWORK Cocoa)
|
find_library(COCOA_FRAMEWORK Cocoa)
|
||||||
find_library(IOKIT_FRAMEWORK IOKit)
|
find_library(IOKIT_FRAMEWORK IOKit)
|
||||||
|
|
|
@ -137,8 +137,8 @@ namespace MWBase
|
||||||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
|
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
|
||||||
|
|
||||||
/// Set value for the given ID.
|
/// Set value for the given ID.
|
||||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
|
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
|
||||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
|
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;
|
||||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
|
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
|
||||||
virtual void setValue (const std::string& id, const std::string& value) = 0;
|
virtual void setValue (const std::string& id, const std::string& value) = 0;
|
||||||
virtual void setValue (const std::string& id, int value) = 0;
|
virtual void setValue (const std::string& id, int value) = 0;
|
||||||
|
@ -236,8 +236,8 @@ namespace MWBase
|
||||||
virtual void onFrame (float frameDuration) = 0;
|
virtual void onFrame (float frameDuration) = 0;
|
||||||
|
|
||||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues() = 0;
|
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
|
||||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues() = 0;
|
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
|
||||||
virtual SkillList getPlayerMinorSkills() = 0;
|
virtual SkillList getPlayerMinorSkills() = 0;
|
||||||
virtual SkillList getPlayerMajorSkills() = 0;
|
virtual SkillList getPlayerMajorSkills() = 0;
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace MWBase
|
||||||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||||
///< get north vector (OGRE coordinates) for given interior cell
|
///< get north vector (OGRE coordinates) for given interior cell
|
||||||
|
|
||||||
virtual std::vector<DoorMarker> getDoorMarkers (MWWorld::CellStore* cell) = 0;
|
virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector<DoorMarker>& out) = 0;
|
||||||
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
///< get a list of teleport door markers for a given cell, to be displayed on the local map
|
||||||
|
|
||||||
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
virtual void getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y) = 0;
|
||||||
|
@ -428,7 +428,28 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
virtual bool isNight() const = 0;
|
// Are we in an exterior or pseudo-exterior cell and it's night?
|
||||||
|
virtual bool isDark() const = 0;
|
||||||
|
|
||||||
|
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0;
|
||||||
|
|
||||||
|
/// Teleports \a ptr to the reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
|
||||||
|
/// closest to \a worldPos.
|
||||||
|
/// @note id must be lower case
|
||||||
|
virtual void teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||||
|
const std::string& id, Ogre::Vector3 worldPos) = 0;
|
||||||
|
|
||||||
|
enum DetectionType
|
||||||
|
{
|
||||||
|
Detect_Enchantment,
|
||||||
|
Detect_Key,
|
||||||
|
Detect_Creature
|
||||||
|
};
|
||||||
|
/// List all references (filtered by \a type) detected by \a ptr. The range
|
||||||
|
/// is determined by the current magnitude of the "Detect X" magic effect belonging to \a type.
|
||||||
|
/// @note This also works for references in containers.
|
||||||
|
virtual void listDetectedReferences (const MWWorld::Ptr& ptr, std::vector<MWWorld::Ptr>& out,
|
||||||
|
DetectionType type) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -291,14 +291,16 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc);
|
||||||
|
|
||||||
|
if (ptr.getCellRef().mCharge == 0)
|
||||||
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
// slots that this item can be equipped in
|
// slots that this item can be equipped in
|
||||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||||
|
|
||||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
if (slots_.first.empty())
|
||||||
|
return std::make_pair(0, "");
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||||
slot!=slots_.first.end(); ++slot)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
||||||
|
@ -306,29 +308,19 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
|
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
|
||||||
|
|
||||||
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
|
|
||||||
{
|
|
||||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||||
{
|
{
|
||||||
if((*itr).mPart == ESM::PRT_Head)
|
if((*itr).mPart == ESM::PRT_Head)
|
||||||
{
|
|
||||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*slot == MWWorld::InventoryStore::Slot_Boots)
|
|
||||||
{
|
|
||||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
|
||||||
{
|
|
||||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||||
{
|
|
||||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||||
|
slot!=slots_.first.end(); ++slot)
|
||||||
|
{
|
||||||
|
// If equipping a shield, check if there's a twohanded weapon conflicting with it
|
||||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
|
|
@ -235,11 +235,10 @@ namespace MWClass
|
||||||
// slots that this item can be equipped in
|
// slots that this item can be equipped in
|
||||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||||
|
|
||||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
if (slots_.first.empty())
|
||||||
|
return std::make_pair(0, "");
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||||
slot!=slots_.first.end(); ++slot)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
|
||||||
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace);
|
||||||
|
@ -247,25 +246,15 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
|
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
|
||||||
|
|
||||||
if(*slot == MWWorld::InventoryStore::Slot_Helmet)
|
|
||||||
{
|
|
||||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||||
{
|
{
|
||||||
if((*itr).mPart == ESM::PRT_Head)
|
if((*itr).mPart == ESM::PRT_Head)
|
||||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*slot == MWWorld::InventoryStore::Slot_Boots)
|
|
||||||
{
|
|
||||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
|
||||||
{
|
|
||||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair (1, "");
|
return std::make_pair (1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,11 @@ namespace MWClass
|
||||||
item.get<ESM::Miscellaneous>();
|
item.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc)
|
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc)
|
||||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001");
|
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")
|
||||||
|
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_005")
|
||||||
|
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_010")
|
||||||
|
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_025")
|
||||||
|
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_100");
|
||||||
}
|
}
|
||||||
|
|
||||||
float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const
|
float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const
|
||||||
|
@ -252,4 +256,11 @@ namespace MWClass
|
||||||
return ref->mBase->mData.mWeight;
|
return ref->mBase->mData.mWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Miscellaneous::isKey(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||||
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
return ref->mBase->mData.mIsKey;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,8 @@ namespace MWClass
|
||||||
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
virtual float getWeight (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
|
||||||
|
|
||||||
|
virtual bool isKey (const MWWorld::Ptr &ptr) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
#include "../mwmechanics/disease.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontalk.hpp"
|
#include "../mwworld/actiontalk.hpp"
|
||||||
|
@ -210,7 +211,7 @@ namespace
|
||||||
+ 5
|
+ 5
|
||||||
+ raceBonus
|
+ raceBonus
|
||||||
+ specBonus
|
+ specBonus
|
||||||
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100.0f));
|
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,8 +451,8 @@ namespace MWClass
|
||||||
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||||
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||||
hitchance *= stats.getFatigueTerm();
|
hitchance *= stats.getFatigueTerm();
|
||||||
hitchance += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyAttack)).mMagnitude -
|
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
|
||||||
mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
|
||||||
hitchance -= otherstats.getEvasion();
|
hitchance -= otherstats.getEvasion();
|
||||||
|
|
||||||
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
||||||
|
@ -493,6 +494,11 @@ namespace MWClass
|
||||||
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||||
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||||
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
|
||||||
|
|
||||||
|
// Weapon broken? unequip it
|
||||||
|
if (weapon.getCellRef().mCharge == 0)
|
||||||
|
weapon = *inv.unequipItem(weapon, ptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
healthdmg = true;
|
healthdmg = true;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +518,8 @@ namespace MWClass
|
||||||
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f);
|
healthdmg = (otherstats.getFatigue().getCurrent() < 1.0f)
|
||||||
|
|| (otherstats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0);
|
||||||
if(stats.isWerewolf())
|
if(stats.isWerewolf())
|
||||||
{
|
{
|
||||||
healthdmg = true;
|
healthdmg = true;
|
||||||
|
@ -598,6 +605,9 @@ namespace MWClass
|
||||||
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!attacker.isEmpty())
|
||||||
|
MWMechanics::diseaseContact(ptr, attacker);
|
||||||
|
|
||||||
if(damage > 0.0f)
|
if(damage > 0.0f)
|
||||||
{
|
{
|
||||||
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
// 'ptr' is losing health. Play a 'hit' voiced dialog entry if not already saying
|
||||||
|
@ -645,6 +655,11 @@ namespace MWClass
|
||||||
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
armorref.mCharge = armor.get<ESM::Armor>()->mBase->mData.mHealth;
|
||||||
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
armorref.mCharge -= std::min(std::max(1, (int)damagediff),
|
||||||
armorref.mCharge);
|
armorref.mCharge);
|
||||||
|
|
||||||
|
// Armor broken? unequip it
|
||||||
|
if (armorref.mCharge == 0)
|
||||||
|
inv.unequipItem(armor, ptr);
|
||||||
|
|
||||||
switch(get(armor).getEquipmentSkill(armor))
|
switch(get(armor).getEquipmentSkill(armor))
|
||||||
{
|
{
|
||||||
case ESM::Skill::LightArmor:
|
case ESM::Skill::LightArmor:
|
||||||
|
@ -839,10 +854,11 @@ namespace MWClass
|
||||||
float moveSpeed;
|
float moveSpeed;
|
||||||
if(normalizedEncumbrance >= 1.0f)
|
if(normalizedEncumbrance >= 1.0f)
|
||||||
moveSpeed = 0.0f;
|
moveSpeed = 0.0f;
|
||||||
else if(mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude > 0)
|
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
|
||||||
|
world->isLevitationEnabled())
|
||||||
{
|
{
|
||||||
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||||
mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude);
|
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||||
flySpeed = std::max(0.0f, flySpeed);
|
flySpeed = std::max(0.0f, flySpeed);
|
||||||
|
@ -853,7 +869,7 @@ namespace MWClass
|
||||||
float swimSpeed = walkSpeed;
|
float swimSpeed = walkSpeed;
|
||||||
if(Npc::getStance(ptr, Run, false))
|
if(Npc::getStance(ptr, Run, false))
|
||||||
swimSpeed = runSpeed;
|
swimSpeed = runSpeed;
|
||||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(MWMechanics::EffectKey(1/*swift swim*/)).mMagnitude;
|
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||||
fSwimRunAthleticsMult->getFloat();
|
fSwimRunAthleticsMult->getFloat();
|
||||||
moveSpeed = swimSpeed;
|
moveSpeed = swimSpeed;
|
||||||
|
@ -887,7 +903,7 @@ namespace MWClass
|
||||||
float x = fJumpAcrobaticsBase->getFloat() +
|
float x = fJumpAcrobaticsBase->getFloat() +
|
||||||
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
||||||
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
||||||
x += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude * 64;
|
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
||||||
x *= encumbranceTerm;
|
x *= encumbranceTerm;
|
||||||
|
|
||||||
if(Npc::getStance(ptr, Run, false))
|
if(Npc::getStance(ptr, Run, false))
|
||||||
|
@ -910,7 +926,7 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||||
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
|
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
|
||||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
|
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
||||||
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
||||||
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||||
|
@ -1015,8 +1031,8 @@ namespace MWClass
|
||||||
if(!stats.isWerewolf())
|
if(!stats.isWerewolf())
|
||||||
{
|
{
|
||||||
weight = getContainerStore(ptr).getWeight();
|
weight = getContainerStore(ptr).getWeight();
|
||||||
weight -= stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).mMagnitude;
|
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude;
|
||||||
weight += stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).mMagnitude;
|
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude;
|
||||||
if(weight < 0.0f)
|
if(weight < 0.0f)
|
||||||
weight = 0.0f;
|
weight = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,14 +388,14 @@ namespace MWClass
|
||||||
|
|
||||||
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
std::pair<int, std::string> Weapon::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const
|
||||||
{
|
{
|
||||||
|
if (ptr.getCellRef().mCharge == 0)
|
||||||
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||||
|
|
||||||
// equip the item in the first free slot
|
if (slots_.first.empty())
|
||||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
return std::make_pair (0, "");
|
||||||
slot!=slots_.first.end(); ++slot)
|
|
||||||
{
|
|
||||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
|
||||||
{
|
|
||||||
if(ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
|
if(ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
|
||||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
|
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
|
||||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
|
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
|
||||||
|
@ -406,11 +406,9 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
return std::make_pair (2, "");
|
return std::make_pair (2, "");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return std::make_pair(1, "");
|
return std::make_pair(1, "");
|
||||||
}
|
}
|
||||||
return std::make_pair (0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
|
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -251,7 +251,7 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::executeTopic (const std::string& topic, bool randomResponse)
|
void DialogueManager::executeTopic (const std::string& topic)
|
||||||
{
|
{
|
||||||
Filter filter (mActor, mChoice, mTalkedTo);
|
Filter filter (mActor, mChoice, mTalkedTo);
|
||||||
|
|
||||||
|
@ -262,12 +262,9 @@ namespace MWDialogue
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||||
|
|
||||||
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, true, true);
|
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||||
|
if (info)
|
||||||
if (!infos.empty())
|
|
||||||
{
|
{
|
||||||
const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0];
|
|
||||||
|
|
||||||
parseText (info->mResponse);
|
parseText (info->mResponse);
|
||||||
|
|
||||||
std::string title;
|
std::string title;
|
||||||
|
@ -509,7 +506,7 @@ namespace MWDialogue
|
||||||
text = "Bribe";
|
text = "Bribe";
|
||||||
}
|
}
|
||||||
|
|
||||||
executeTopic (text + (success ? " Success" : " Fail"), true);
|
executeTopic (text + (success ? " Success" : " Fail"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DialogueManager::getTemporaryDispositionChange() const
|
int DialogueManager::getTemporaryDispositionChange() const
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace MWDialogue
|
||||||
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
||||||
void executeScript (const std::string& script);
|
void executeScript (const std::string& script);
|
||||||
|
|
||||||
void executeTopic (const std::string& topic, bool randomResponse=false);
|
void executeTopic (const std::string& topic);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/journal.hpp"
|
#include "../mwbase/journal.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
@ -133,7 +134,8 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
|
||||||
if (isCreature)
|
if (isCreature)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
|
int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor)
|
||||||
|
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange();
|
||||||
// For service refusal, the disposition check is inverted. However, a value of 0 still means "always succeed".
|
// For service refusal, the disposition check is inverted. However, a value of 0 still means "always succeed".
|
||||||
return invert ? (info.mData.mDisposition == 0 || actorDisposition < info.mData.mDisposition)
|
return invert ? (info.mData.mDisposition == 0 || actorDisposition < info.mData.mDisposition)
|
||||||
: (actorDisposition >= info.mData.mDisposition);
|
: (actorDisposition >= info.mData.mDisposition);
|
||||||
|
|
|
@ -44,6 +44,11 @@ namespace MWGui
|
||||||
adjustButton(mNextPageButton);
|
adjustButton(mNextPageButton);
|
||||||
adjustButton(mPrevPageButton);
|
adjustButton(mPrevPageButton);
|
||||||
|
|
||||||
|
mLeftPage->setNeedMouseFocus(true);
|
||||||
|
mLeftPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||||
|
mRightPage->setNeedMouseFocus(true);
|
||||||
|
mRightPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||||
|
|
||||||
if (mNextPageButton->getSize().width == 64)
|
if (mNextPageButton->getSize().width == 64)
|
||||||
{
|
{
|
||||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||||
|
@ -54,6 +59,14 @@ namespace MWGui
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BookWindow::onMouseWheel(MyGUI::Widget *_sender, int _rel)
|
||||||
|
{
|
||||||
|
if (_rel < 0)
|
||||||
|
nextPage();
|
||||||
|
else
|
||||||
|
prevPage();
|
||||||
|
}
|
||||||
|
|
||||||
void BookWindow::clearPages()
|
void BookWindow::clearPages()
|
||||||
{
|
{
|
||||||
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
|
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
|
||||||
|
@ -89,6 +102,7 @@ namespace MWGui
|
||||||
parent = mRightPage;
|
parent = mRightPage;
|
||||||
|
|
||||||
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
|
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
|
||||||
|
pageWidget->setNeedMouseFocus(false);
|
||||||
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
|
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
|
||||||
mPages.push_back(pageWidget);
|
mPages.push_back(pageWidget);
|
||||||
++i;
|
++i;
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace MWGui
|
||||||
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
||||||
void onCloseButtonClicked (MyGUI::Widget* sender);
|
void onCloseButtonClicked (MyGUI::Widget* sender);
|
||||||
void onTakeButtonClicked (MyGUI::Widget* sender);
|
void onTakeButtonClicked (MyGUI::Widget* sender);
|
||||||
|
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
|
|
||||||
void updatePages();
|
void updatePages();
|
||||||
void clearPages();
|
void clearPages();
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace MWGui
|
||||||
mGenerateClassSpecializations[2] = 0;
|
mGenerateClassSpecializations[2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
if (mReviewDialog)
|
if (mReviewDialog)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
if (mReviewDialog)
|
if (mReviewDialog)
|
||||||
mReviewDialog->setSkillValue(parSkill, value);
|
mReviewDialog->setSkillValue(parSkill, value);
|
||||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::map<int, MWMechanics::Stat<int> > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||||
for (std::map<int, MWMechanics::Stat<int> >::iterator it = attributes.begin();
|
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
|
||||||
it != attributes.end(); ++it)
|
it != attributes.end(); ++it)
|
||||||
{
|
{
|
||||||
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
|
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
|
||||||
|
@ -238,8 +238,8 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::map<int, MWMechanics::Stat<float> > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||||
for (std::map<int, MWMechanics::Stat<float> >::iterator it = skills.begin();
|
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
|
||||||
it != skills.end(); ++it)
|
it != skills.end(); ++it)
|
||||||
{
|
{
|
||||||
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
||||||
|
|
|
@ -31,9 +31,9 @@ namespace MWGui
|
||||||
//Show a dialog
|
//Show a dialog
|
||||||
void spawnDialog(const char id);
|
void spawnDialog(const char id);
|
||||||
|
|
||||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||||
void doRenderUpdate();
|
void doRenderUpdate();
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,6 @@ namespace MWGui
|
||||||
|
|
||||||
// Set up the log window
|
// Set up the log window
|
||||||
mHistory->setOverflowToTheLeft(true);
|
mHistory->setOverflowToTheLeft(true);
|
||||||
mHistory->setEditStatic(true);
|
|
||||||
mHistory->setVisibleVScroll(true);
|
|
||||||
|
|
||||||
// compiler
|
// compiler
|
||||||
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
|
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
|
||||||
|
@ -215,7 +213,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
std::vector<std::string> matches;
|
std::vector<std::string> matches;
|
||||||
listNames();
|
listNames();
|
||||||
mCommandLine->setCaption(complete( mCommandLine->getCaption(), matches ));
|
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
|
||||||
#if 0
|
#if 0
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
||||||
|
@ -234,7 +232,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
// If the user was editing a string, store it for later
|
// If the user was editing a string, store it for later
|
||||||
if(mCurrent == mCommandHistory.end())
|
if(mCurrent == mCommandHistory.end())
|
||||||
mEditString = mCommandLine->getCaption();
|
mEditString = mCommandLine->getOnlyText();
|
||||||
|
|
||||||
if(mCurrent != mCommandHistory.begin())
|
if(mCurrent != mCommandHistory.begin())
|
||||||
{
|
{
|
||||||
|
@ -259,7 +257,7 @@ namespace MWGui
|
||||||
|
|
||||||
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
||||||
{
|
{
|
||||||
const std::string &cm = mCommandLine->getCaption();
|
const std::string &cm = mCommandLine->getOnlyText();
|
||||||
if(cm.empty()) return;
|
if(cm.empty()) return;
|
||||||
|
|
||||||
// Add the command to the history, and set the current pointer to
|
// Add the command to the history, and set the current pointer to
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace MWGui
|
||||||
, mWorldMouseOver(false)
|
, mWorldMouseOver(false)
|
||||||
, mEnemyHealthTimer(0)
|
, mEnemyHealthTimer(0)
|
||||||
, mIsDrowning(false)
|
, mIsDrowning(false)
|
||||||
|
, mWeaponSpellTimer(0.f)
|
||||||
|
, mDrowningFlashTheta(0.f)
|
||||||
{
|
{
|
||||||
setCoord(0,0, width, height);
|
setCoord(0,0, width, height);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ void InventoryItemModel::update()
|
||||||
// NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken.
|
// NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken.
|
||||||
// Vanilla likely uses a hack like this since there's no other way to prevent it from
|
// Vanilla likely uses a hack like this since there's no other way to prevent it from
|
||||||
// being shown or taken.
|
// being shown or taken.
|
||||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ItemStack newItem (item, this, item.getRefData().getCount());
|
ItemStack newItem (item, this, item.getRefData().getCount());
|
||||||
|
|
|
@ -163,6 +163,14 @@ namespace MWGui
|
||||||
MWWorld::Ptr object = item.mBase;
|
MWWorld::Ptr object = item.mBase;
|
||||||
int count = item.mCount;
|
int count = item.mCount;
|
||||||
|
|
||||||
|
// Bound items may not be moved
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (item.mType == ItemStack::Type_Equipped)
|
if (item.mType == ItemStack::Type_Equipped)
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||||
|
@ -417,7 +425,7 @@ namespace MWGui
|
||||||
// NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla
|
// NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla
|
||||||
// likely uses a hack like this since there's no other way to prevent it from being
|
// likely uses a hack like this since there's no other way to prevent it from being
|
||||||
// taken.
|
// taken.
|
||||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ namespace MWGui
|
||||||
// increase attributes
|
// increase attributes
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
MWMechanics::Stat<int> attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
MWMechanics::AttributeValue attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
||||||
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
||||||
|
|
||||||
if (attribute.getBase() >= 100)
|
if (attribute.getBase() >= 100)
|
||||||
|
|
|
@ -103,27 +103,80 @@ namespace MWGui
|
||||||
|
|
||||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||||
{
|
{
|
||||||
|
// Workaround to not make the marker visible if it's under fog of war
|
||||||
applyFogOfWar ();
|
applyFogOfWar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||||
{
|
{
|
||||||
|
// Workaround to not make the marker visible if it's under fog of war
|
||||||
applyFogOfWar ();
|
applyFogOfWar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
|
||||||
|
{
|
||||||
|
MyGUI::IntPoint widgetPos;
|
||||||
|
// normalized cell coordinates
|
||||||
|
float nX,nY;
|
||||||
|
|
||||||
|
markerPos.interior = mInterior;
|
||||||
|
|
||||||
|
if (!mInterior)
|
||||||
|
{
|
||||||
|
int cellX, cellY;
|
||||||
|
MWBase::Environment::get().getWorld()->positionToIndex(worldX, worldY, cellX, cellY);
|
||||||
|
const int cellSize = 8192;
|
||||||
|
nX = (worldX - cellSize * cellX) / cellSize;
|
||||||
|
// Image space is -Y up, cells are Y up
|
||||||
|
nY = 1 - (worldY - cellSize * cellY) / cellSize;
|
||||||
|
|
||||||
|
float cellDx = cellX - mCurX;
|
||||||
|
float cellDy = cellY - mCurY;
|
||||||
|
|
||||||
|
markerPos.cellX = cellX;
|
||||||
|
markerPos.cellY = cellY;
|
||||||
|
|
||||||
|
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellDx) * 512,
|
||||||
|
nY * 512 - (cellDy-1) * 512);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int cellX, cellY;
|
||||||
|
Ogre::Vector2 worldPos (worldX, worldY);
|
||||||
|
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (worldPos, nX, nY, cellX, cellY);
|
||||||
|
|
||||||
|
markerPos.cellX = cellX;
|
||||||
|
markerPos.cellY = cellY;
|
||||||
|
|
||||||
|
widgetPos = MyGUI::IntPoint(nX * 512 + (1+cellX-mCurX) * 512,
|
||||||
|
nY * 512 + (1+cellY-mCurY) * 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
markerPos.nX = nX;
|
||||||
|
markerPos.nY = nY;
|
||||||
|
return widgetPos;
|
||||||
|
}
|
||||||
|
|
||||||
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
|
||||||
{
|
{
|
||||||
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
|
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged)
|
||||||
|
return; // don't do anything if we're still in the same cell
|
||||||
|
|
||||||
|
mCurX = x;
|
||||||
|
mCurY = y;
|
||||||
|
mInterior = interior;
|
||||||
|
mChanged = false;
|
||||||
|
|
||||||
// clear all previous markers
|
// clear all previous markers
|
||||||
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||||
{
|
{
|
||||||
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
if (mLocalMap->getChildAt(i)->getName ().substr (0, 4) == "Door")
|
||||||
{
|
{
|
||||||
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the map textures
|
||||||
for (int mx=0; mx<3; ++mx)
|
for (int mx=0; mx<3; ++mx)
|
||||||
{
|
{
|
||||||
for (int my=0; my<3; ++my)
|
for (int my=0; my<3; ++my)
|
||||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
||||||
box->setImageTexture(image);
|
box->setImageTexture(image);
|
||||||
else
|
else
|
||||||
box->setImageTexture("black.png");
|
box->setImageTexture("black.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
// door markers
|
// Retrieve the door markers we want to show
|
||||||
|
std::vector<MWBase::World::DoorMarker> doors;
|
||||||
// interior map only consists of one cell, so handle the markers only once
|
|
||||||
if (interior && (mx != 2 || my != 2))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MWWorld::CellStore* cell;
|
|
||||||
if (interior)
|
if (interior)
|
||||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
{
|
||||||
|
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||||
|
world->getDoorMarkers(cell, doors);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
{
|
||||||
|
for (int dX=-1; dX<2; ++dX)
|
||||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
{
|
||||||
|
for (int dY=-1; dY<2; ++dY)
|
||||||
|
{
|
||||||
|
MWWorld::CellStore* cell = world->getExterior (mCurX+dX, mCurY+dY);
|
||||||
|
world->getDoorMarkers(cell, doors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a widget for each marker
|
||||||
|
int counter = 0;
|
||||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||||
{
|
{
|
||||||
MWBase::World::DoorMarker marker = *it;
|
MWBase::World::DoorMarker marker = *it;
|
||||||
|
|
||||||
// convert world coordinates to normalized cell coordinates
|
MarkerPosition markerPos;
|
||||||
MyGUI::IntCoord widgetCoord;
|
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||||
float nX,nY;
|
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||||
int cellDx, cellDy;
|
widgetPos.top - 4,
|
||||||
if (!interior)
|
8, 8);
|
||||||
{
|
|
||||||
const int cellSize = 8192;
|
|
||||||
|
|
||||||
nX = (marker.x - cellSize * (x+mx-1)) / cellSize;
|
|
||||||
nY = 1 - (marker.y - cellSize * (y-(my-1))) / cellSize;
|
|
||||||
|
|
||||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + mx * 512, nY * 512 - 4 + my * 512, 8, 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Ogre::Vector2 position (marker.x, marker.y);
|
|
||||||
MWBase::Environment::get().getWorld ()->getInteriorMapPosition (position, nX, nY, cellDx, cellDy);
|
|
||||||
|
|
||||||
widgetCoord = MyGUI::IntCoord(nX * 512 - 4 + (1+cellDx-x) * 512, nY * 512 - 4 + (1+cellDy-y) * 512, 8, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int counter = 0;
|
|
||||||
++counter;
|
++counter;
|
||||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
|
||||||
markerWidget->setImageResource("DoorMarker");
|
markerWidget->setImageResource("DoorMarker");
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||||
markerWidget->setUserString("IsMarker", "true");
|
|
||||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||||
|
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||||
MarkerPosition markerPos;
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
markerPos.interior = interior;
|
|
||||||
markerPos.cellX = interior ? cellDx : x + mx - 1;
|
|
||||||
markerPos.cellY = interior ? cellDy : y + ((my - 1)*-1);
|
|
||||||
markerPos.nX = nX;
|
|
||||||
markerPos.nY = nY;
|
|
||||||
|
|
||||||
markerWidget->setUserData(markerPos);
|
markerWidget->setUserData(markerPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMarkers();
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mInterior = interior;
|
|
||||||
mCurX = x;
|
|
||||||
mCurY = y;
|
|
||||||
mChanged = false;
|
|
||||||
|
|
||||||
// fog of war
|
|
||||||
applyFogOfWar();
|
applyFogOfWar();
|
||||||
|
|
||||||
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
|
||||||
|
@ -222,6 +254,8 @@ namespace MWGui
|
||||||
|
|
||||||
void LocalMapBase::setPlayerPos(const float x, const float y)
|
void LocalMapBase::setPlayerPos(const float x, const float y)
|
||||||
{
|
{
|
||||||
|
updateMarkers();
|
||||||
|
|
||||||
if (x == mLastPositionX && y == mLastPositionY)
|
if (x == mLastPositionX && y == mLastPositionY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
||||||
mLastDirectionY = y;
|
mLastDirectionY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::addDetectionMarkers(int type)
|
||||||
|
{
|
||||||
|
std::vector<MWWorld::Ptr> markers;
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
world->listDetectedReferences(
|
||||||
|
world->getPlayer().getPlayer(),
|
||||||
|
markers, MWBase::World::DetectionType(type));
|
||||||
|
if (markers.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string markerTexture;
|
||||||
|
MyGUI::Colour markerColour;
|
||||||
|
if (type == MWBase::World::Detect_Creature)
|
||||||
|
{
|
||||||
|
markerTexture = "textures\\menu_map_dcreature.dds";
|
||||||
|
markerColour = MyGUI::Colour(1,0,0,1);
|
||||||
|
}
|
||||||
|
if (type == MWBase::World::Detect_Key)
|
||||||
|
{
|
||||||
|
markerTexture = "textures\\menu_map_dkey.dds";
|
||||||
|
markerColour = MyGUI::Colour(0,1,0,1);
|
||||||
|
}
|
||||||
|
if (type == MWBase::World::Detect_Enchantment)
|
||||||
|
{
|
||||||
|
markerTexture = "textures\\menu_map_dmagic.dds";
|
||||||
|
markerColour = MyGUI::Colour(0,0,1,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::Position& worldPos = it->getRefData().getPosition();
|
||||||
|
MarkerPosition markerPos;
|
||||||
|
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
|
||||||
|
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||||
|
widgetPos.top - 4,
|
||||||
|
8, 8);
|
||||||
|
++counter;
|
||||||
|
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||||
|
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||||
|
markerWidget->setImageTexture(markerTexture);
|
||||||
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
|
markerWidget->setUserData(markerPos);
|
||||||
|
markerWidget->setColour(markerColour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalMapBase::updateMarkers()
|
||||||
|
{
|
||||||
|
// clear all previous markers
|
||||||
|
for (unsigned int i=0; i< mLocalMap->getChildCount(); ++i)
|
||||||
|
{
|
||||||
|
if (mLocalMap->getChildAt(i)->getName ().substr (0, 6) == "Marker")
|
||||||
|
{
|
||||||
|
MyGUI::Gui::getInstance ().destroyWidget (mLocalMap->getChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDetectionMarkers(MWBase::World::Detect_Creature);
|
||||||
|
addDetectionMarkers(MWBase::World::Detect_Key);
|
||||||
|
addDetectionMarkers(MWBase::World::Detect_Enchantment);
|
||||||
|
|
||||||
|
// Add marker for the spot marked with Mark magic effect
|
||||||
|
MWWorld::CellStore* markedCell = NULL;
|
||||||
|
ESM::Position markedPosition;
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||||
|
if (markedCell && markedCell->isExterior() == !mInterior
|
||||||
|
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->mCell->mName, mPrefix)))
|
||||||
|
{
|
||||||
|
MarkerPosition markerPos;
|
||||||
|
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
|
||||||
|
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||||
|
widgetPos.top - 4,
|
||||||
|
8, 8);
|
||||||
|
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
|
||||||
|
widgetCoord, MyGUI::Align::Default, "MarkerMarked");
|
||||||
|
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
|
||||||
|
markerWidget->setUserString("IsMarker", "true");
|
||||||
|
markerWidget->setUserData(markerPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
MapWindow::MapWindow(const std::string& cacheDir)
|
MapWindow::MapWindow(const std::string& cacheDir)
|
||||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
||||||
|
|
||||||
static int _counter=0;
|
static int _counter=0;
|
||||||
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
|
||||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
|
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||||
markerWidget->setImageResource("DoorMarker");
|
markerWidget->setImageResource("DoorMarker");
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
|
||||||
{
|
{
|
||||||
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
|
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,4) == "Door")
|
||||||
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +511,9 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::globalMapUpdatePlayer ()
|
void MapWindow::globalMapUpdatePlayer ()
|
||||||
|
{
|
||||||
|
// For interiors, position is set by WindowManager via setGlobalMapPlayerPosition
|
||||||
|
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
|
||||||
{
|
{
|
||||||
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
|
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
|
||||||
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
|
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
|
||||||
|
@ -405,11 +524,6 @@ namespace MWGui
|
||||||
worldX *= mGlobalMapRender->getWidth();
|
worldX *= mGlobalMapRender->getWidth();
|
||||||
worldY *= mGlobalMapRender->getHeight();
|
worldY *= mGlobalMapRender->getHeight();
|
||||||
|
|
||||||
|
|
||||||
// for interiors, we have no choice other than using the last position & direction.
|
|
||||||
/// \todo save this last position in the savegame?
|
|
||||||
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
|
|
||||||
{
|
|
||||||
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
|
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
|
||||||
|
|
||||||
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
|
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
|
||||||
|
@ -444,4 +558,19 @@ namespace MWGui
|
||||||
"#{sWorld}");
|
"#{sWorld}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapWindow::setGlobalMapPlayerPosition(float worldX, float worldY)
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
mGlobalMapRender->worldPosToImageSpace (worldX, worldY, x, y);
|
||||||
|
x *= mGlobalMapRender->getWidth();
|
||||||
|
y *= mGlobalMapRender->getHeight();
|
||||||
|
|
||||||
|
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(x - 16, y - 16));
|
||||||
|
|
||||||
|
// set the view offset so that player is in the center
|
||||||
|
MyGUI::IntSize viewsize = mGlobalMap->getSize();
|
||||||
|
MyGUI::IntPoint viewoffs(0.5*viewsize.width - x, 0.5*viewsize.height - y);
|
||||||
|
mGlobalMap->setViewOffset(viewoffs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,16 @@ namespace MWGui
|
||||||
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
void onMarkerFocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||||
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
void onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||||
|
|
||||||
|
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
|
||||||
|
|
||||||
virtual void notifyPlayerUpdate() {}
|
virtual void notifyPlayerUpdate() {}
|
||||||
virtual void notifyMapChanged() {}
|
virtual void notifyMapChanged() {}
|
||||||
|
|
||||||
|
// Update markers (Detect X effects, Mark/Recall effects)
|
||||||
|
// Note, door markers handled in setActiveCell
|
||||||
|
void updateMarkers();
|
||||||
|
void addDetectionMarkers(int type);
|
||||||
|
|
||||||
OEngine::GUI::Layout* mLayout;
|
OEngine::GUI::Layout* mLayout;
|
||||||
|
|
||||||
bool mMapDragAndDrop;
|
bool mMapDragAndDrop;
|
||||||
|
@ -81,6 +88,8 @@ namespace MWGui
|
||||||
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
|
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
|
||||||
void cellExplored(int x, int y);
|
void cellExplored(int x, int y);
|
||||||
|
|
||||||
|
void setGlobalMapPlayerPosition (float worldX, float worldY);
|
||||||
|
|
||||||
virtual void open();
|
virtual void open();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -16,6 +16,15 @@ namespace MWGui
|
||||||
mLastButtonPressed = -1;
|
mLastButtonPressed = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageBoxManager::~MessageBoxManager ()
|
||||||
|
{
|
||||||
|
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
|
||||||
|
for (; it != mMessageBoxes.end(); ++it)
|
||||||
|
{
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MessageBoxManager::onFrame (float frameDuration)
|
void MessageBoxManager::onFrame (float frameDuration)
|
||||||
{
|
{
|
||||||
std::vector<MessageBox*>::iterator it;
|
std::vector<MessageBox*>::iterator it;
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MessageBoxManager ();
|
MessageBoxManager ();
|
||||||
|
~MessageBoxManager ();
|
||||||
void onFrame (float frameDuration);
|
void onFrame (float frameDuration);
|
||||||
void createMessageBox (const std::string& message, bool stat = false);
|
void createMessageBox (const std::string& message, bool stat = false);
|
||||||
void removeStaticMessageBox ();
|
void removeStaticMessageBox ();
|
||||||
|
|
|
@ -40,6 +40,14 @@ namespace MWGui
|
||||||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
||||||
{
|
{
|
||||||
const ItemStack& item = mSourceModel->getItem(i);
|
const ItemStack& item = mSourceModel->getItem(i);
|
||||||
|
|
||||||
|
// Bound items may not be stolen
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
|
if (std::find(mHiddenItems.begin(), mHiddenItems.end(), item) == mHiddenItems.end()
|
||||||
&& item.mType != ItemStack::Type_Equipped)
|
&& item.mType != ItemStack::Type_Equipped)
|
||||||
mItems.push_back(item);
|
mItems.push_back(item);
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace MWGui
|
||||||
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
|
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
|
||||||
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
|
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
|
||||||
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
|
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
|
||||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
|
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup skills
|
// Setup skills
|
||||||
|
@ -74,7 +74,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
mSkillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
|
mSkillValues.insert(std::make_pair(i, MWMechanics::SkillValue()));
|
||||||
mSkillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
|
mSkillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace MWGui
|
||||||
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
|
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
|
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
|
||||||
if (attr == mAttributeWidgets.end())
|
if (attr == mAttributeWidgets.end())
|
||||||
|
@ -161,7 +161,7 @@ namespace MWGui
|
||||||
attr->second->setAttributeValue(value);
|
attr->second->setAttributeValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
|
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
mSkillValues[skillId] = value;
|
mSkillValues[skillId] = value;
|
||||||
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
|
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
|
||||||
|
@ -279,9 +279,9 @@ namespace MWGui
|
||||||
continue;
|
continue;
|
||||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||||
float base = stat.getBase();
|
int base = stat.getBase();
|
||||||
float modified = stat.getModified();
|
int modified = stat.getModified();
|
||||||
|
|
||||||
std::string state = "normal";
|
std::string state = "normal";
|
||||||
if (modified > base)
|
if (modified > base)
|
||||||
|
|
|
@ -38,10 +38,10 @@ namespace MWGui
|
||||||
void setMagicka(const MWMechanics::DynamicStat<float>& value);
|
void setMagicka(const MWMechanics::DynamicStat<float>& value);
|
||||||
void setFatigue(const MWMechanics::DynamicStat<float>& value);
|
void setFatigue(const MWMechanics::DynamicStat<float>& value);
|
||||||
|
|
||||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);
|
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value);
|
||||||
|
|
||||||
void configureSkills(const SkillList& major, const SkillList& minor);
|
void configureSkills(const SkillList& major, const SkillList& minor);
|
||||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value);
|
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value);
|
||||||
|
|
||||||
virtual void open();
|
virtual void open();
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace MWGui
|
||||||
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||||
|
|
||||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||||
std::string mName, mRaceId, mBirthSignId;
|
std::string mName, mRaceId, mBirthSignId;
|
||||||
ESM::Class mKlass;
|
ESM::Class mKlass;
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
void EffectSourceVisitor::visit (MWMechanics::EffectKey key,
|
void EffectSourceVisitor::visit (MWMechanics::EffectKey key,
|
||||||
const std::string& sourceName, float magnitude, float remainingTime)
|
const std::string& sourceName, const std::string& casterHandle,
|
||||||
|
float magnitude, float remainingTime)
|
||||||
{
|
{
|
||||||
MagicEffectInfo newEffectSource;
|
MagicEffectInfo newEffectSource;
|
||||||
newEffectSource.mKey = key;
|
newEffectSource.mKey = key;
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace MWGui
|
||||||
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
|
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
|
||||||
|
|
||||||
virtual void visit (MWMechanics::EffectKey key,
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
const std::string& sourceName, float magnitude, float remainingTime = -1);
|
const std::string& sourceName, const std::string& casterHandle,
|
||||||
|
float magnitude, float remainingTime = -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SpellIcons
|
class SpellIcons
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace MWGui
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
mSkillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
|
mSkillValues.insert(std::pair<int, MWMechanics::SkillValue >(i, MWMechanics::SkillValue()));
|
||||||
mSkillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, (MyGUI::TextBox*)NULL));
|
mSkillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, (MyGUI::TextBox*)NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace MWGui
|
||||||
adjustWindowCaption();
|
adjustWindowCaption();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
void StatsWindow::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
static const char *ids[] =
|
static const char *ids[] =
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
mSkillValues[parSkill] = value;
|
mSkillValues[parSkill] = value;
|
||||||
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
|
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
|
||||||
|
@ -358,22 +358,20 @@ namespace MWGui
|
||||||
continue;
|
continue;
|
||||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||||
float base = stat.getBase();
|
int base = stat.getBase();
|
||||||
float modified = stat.getModified();
|
int modified = stat.getModified();
|
||||||
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
|
int progressPercent = stat.getProgress() * 100;
|
||||||
|
|
||||||
const MWWorld::ESMStore &esmStore =
|
const MWWorld::ESMStore &esmStore =
|
||||||
MWBase::Environment::get().getWorld()->getStore();
|
MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
|
||||||
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
||||||
assert(skill);
|
|
||||||
|
|
||||||
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
||||||
|
|
||||||
const ESM::Attribute* attr =
|
const ESM::Attribute* attr =
|
||||||
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||||
assert(attr);
|
|
||||||
|
|
||||||
std::string state = "normal";
|
std::string state = "normal";
|
||||||
if (modified > base)
|
if (modified > base)
|
||||||
|
@ -484,7 +482,6 @@ namespace MWGui
|
||||||
ESM::RankData rankData = faction->mData.mRankData[it->second+1];
|
ESM::RankData rankData = faction->mData.mRankData[it->second+1];
|
||||||
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
|
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
|
||||||
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
|
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
|
||||||
assert(attr1 && attr2);
|
|
||||||
|
|
||||||
text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute1)
|
text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute1)
|
||||||
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);
|
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);
|
||||||
|
|
|
@ -26,11 +26,11 @@ namespace MWGui
|
||||||
void setPlayerName(const std::string& playerName);
|
void setPlayerName(const std::string& playerName);
|
||||||
|
|
||||||
/// Set value for the given ID.
|
/// Set value for the given ID.
|
||||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||||
void setValue (const std::string& id, const std::string& value);
|
void setValue (const std::string& id, const std::string& value);
|
||||||
void setValue (const std::string& id, int value);
|
void setValue (const std::string& id, int value);
|
||||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||||
|
|
||||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||||
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
|
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
|
||||||
|
@ -61,7 +61,7 @@ namespace MWGui
|
||||||
MyGUI::ScrollView* mSkillView;
|
MyGUI::ScrollView* mSkillView;
|
||||||
|
|
||||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||||
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
||||||
FactionList mFactions; ///< Stores a list of factions and the current rank
|
FactionList mFactions; ///< Stores a list of factions and the current rank
|
||||||
|
|
|
@ -154,6 +154,13 @@ namespace MWGui
|
||||||
if(!MWWorld::Class::get(base).canSell(base, services))
|
if(!MWWorld::Class::get(base).canSell(base, services))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Bound items may not be bought
|
||||||
|
if (item.mBase.getCellRef().mRefID.size() > 6
|
||||||
|
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// don't show equipped items
|
// don't show equipped items
|
||||||
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "containeritemmodel.hpp"
|
#include "containeritemmodel.hpp"
|
||||||
#include "tradeitemmodel.hpp"
|
#include "tradeitemmodel.hpp"
|
||||||
#include "countdialog.hpp"
|
#include "countdialog.hpp"
|
||||||
|
#include "dialogue.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
@ -296,10 +297,10 @@ namespace MWGui
|
||||||
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
||||||
const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
||||||
|
|
||||||
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||||
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||||
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||||
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||||
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||||
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||||
|
|
||||||
|
@ -340,6 +341,9 @@ namespace MWGui
|
||||||
addOrRemoveGold(-mCurrentBalance, mPtr);
|
addOrRemoveGold(-mCurrentBalance, mPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());
|
||||||
|
|
||||||
std::string sound = "Item Gold Up";
|
std::string sound = "Item Gold Up";
|
||||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ namespace MWGui
|
||||||
|
|
||||||
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
|
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
|
||||||
|
|
||||||
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
|
bool stunted = (stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0);
|
||||||
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
|
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
|
||||||
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
if (mAttributeValueWidget)
|
if (mAttributeValueWidget)
|
||||||
{
|
{
|
||||||
AttributeValue::Type modified = mValue.getModified(), base = mValue.getBase();
|
int modified = mValue.getModified(), base = mValue.getBase();
|
||||||
static_cast<MyGUI::TextBox*>(mAttributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
static_cast<MyGUI::TextBox*>(mAttributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
||||||
if (modified > base)
|
if (modified > base)
|
||||||
mAttributeValueWidget->_setWidgetState("increased");
|
mAttributeValueWidget->_setWidgetState("increased");
|
||||||
|
@ -527,16 +527,11 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
if (mBarTextWidget)
|
if (mBarTextWidget)
|
||||||
{
|
|
||||||
if (mValue >= 0 && mMax > 0)
|
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
out << mValue << "/" << mMax;
|
out << mValue << "/" << mMax;
|
||||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void MWDynamicStat::setTitle(const std::string& text)
|
void MWDynamicStat::setTitle(const std::string& text)
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
MWAttribute();
|
MWAttribute();
|
||||||
|
|
||||||
typedef MWMechanics::Stat<int> AttributeValue;
|
typedef MWMechanics::AttributeValue AttributeValue;
|
||||||
|
|
||||||
void setAttributeId(int attributeId);
|
void setAttributeId(int attributeId);
|
||||||
void setAttributeValue(const AttributeValue& value);
|
void setAttributeValue(const AttributeValue& value);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
#include "journalwindow.hpp"
|
#include "journalwindow.hpp"
|
||||||
|
@ -174,11 +175,11 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
||||||
|
|
||||||
mCursorManager->setEnabled(true);
|
|
||||||
|
|
||||||
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||||
SDL_ShowCursor(false);
|
SDL_ShowCursor(false);
|
||||||
|
|
||||||
|
mCursorManager->setEnabled(true);
|
||||||
|
|
||||||
// hide mygui's pointer
|
// hide mygui's pointer
|
||||||
MyGUI::PointerManager::getInstance().setVisible(false);
|
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||||
}
|
}
|
||||||
|
@ -248,12 +249,12 @@ namespace MWGui
|
||||||
// Setup player stats
|
// Setup player stats
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||||
{
|
{
|
||||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::Stat<int>()));
|
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::Stat<float>()));
|
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up visibility
|
// Set up visibility
|
||||||
|
@ -322,6 +323,7 @@ namespace MWGui
|
||||||
delete mSoulgemDialog;
|
delete mSoulgemDialog;
|
||||||
delete mCursorManager;
|
delete mCursorManager;
|
||||||
delete mRecharge;
|
delete mRecharge;
|
||||||
|
delete mCompanionWindow;
|
||||||
|
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
|
||||||
|
@ -542,7 +544,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
void WindowManager::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
mStatsWindow->setValue (id, value);
|
mStatsWindow->setValue (id, value);
|
||||||
mCharGen->setValue(id, value);
|
mCharGen->setValue(id, value);
|
||||||
|
@ -573,7 +575,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& value)
|
void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value)
|
||||||
{
|
{
|
||||||
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
||||||
/// allow custom skills.
|
/// allow custom skills.
|
||||||
|
@ -774,6 +776,13 @@ namespace MWGui
|
||||||
mHud->setCellName( cell->mCell->mName );
|
mHud->setCellName( cell->mCell->mName );
|
||||||
mMap->setCellPrefix( cell->mCell->mName );
|
mMap->setCellPrefix( cell->mCell->mName );
|
||||||
mHud->setCellPrefix( cell->mCell->mName );
|
mHud->setCellPrefix( cell->mCell->mName );
|
||||||
|
|
||||||
|
Ogre::Vector3 worldPos;
|
||||||
|
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos))
|
||||||
|
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
|
||||||
|
else
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos);
|
||||||
|
mMap->setGlobalMapPlayerPosition(worldPos.x, worldPos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1169,12 +1178,12 @@ namespace MWGui
|
||||||
return mGuiModes.back();
|
return mGuiModes.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues()
|
std::map<int, MWMechanics::SkillValue > WindowManager::getPlayerSkillValues()
|
||||||
{
|
{
|
||||||
return mPlayerSkillValues;
|
return mPlayerSkillValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues()
|
std::map<int, MWMechanics::AttributeValue > WindowManager::getPlayerAttributeValues()
|
||||||
{
|
{
|
||||||
return mPlayerAttributes;
|
return mPlayerAttributes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,8 +152,8 @@ namespace MWGui
|
||||||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount);
|
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount);
|
||||||
|
|
||||||
///< Set value for the given ID.
|
///< Set value for the given ID.
|
||||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
|
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value);
|
||||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||||
virtual void setValue (const std::string& id, const std::string& value);
|
virtual void setValue (const std::string& id, const std::string& value);
|
||||||
virtual void setValue (const std::string& id, int value);
|
virtual void setValue (const std::string& id, int value);
|
||||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
||||||
virtual void onFrame (float frameDuration);
|
virtual void onFrame (float frameDuration);
|
||||||
|
|
||||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues();
|
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues();
|
||||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues();
|
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues();
|
||||||
virtual SkillList getPlayerMinorSkills();
|
virtual SkillList getPlayerMinorSkills();
|
||||||
virtual SkillList getPlayerMajorSkills();
|
virtual SkillList getPlayerMajorSkills();
|
||||||
|
|
||||||
|
@ -346,9 +346,9 @@ namespace MWGui
|
||||||
// Various stats about player as needed by window manager
|
// Various stats about player as needed by window manager
|
||||||
std::string mPlayerName;
|
std::string mPlayerName;
|
||||||
std::string mPlayerRaceId;
|
std::string mPlayerRaceId;
|
||||||
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
|
std::map<int, MWMechanics::AttributeValue > mPlayerAttributes;
|
||||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||||
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
|
std::map<int, MWMechanics::SkillValue > mPlayerSkillValues;
|
||||||
|
|
||||||
MyGUI::Gui *mGui; // Gui
|
MyGUI::Gui *mGui; // Gui
|
||||||
std::vector<GuiMode> mGuiModes;
|
std::vector<GuiMode> mGuiModes;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <MyGUI_RenderManager.h>
|
#include <MyGUI_RenderManager.h>
|
||||||
#include <MyGUI_Widget.h>
|
#include <MyGUI_Widget.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
#include <openengine/ogre/renderer.hpp>
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
|
||||||
|
@ -19,7 +20,6 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwgui/bookwindow.hpp"
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
using namespace ICS;
|
using namespace ICS;
|
||||||
|
@ -497,6 +497,9 @@ namespace MWInput
|
||||||
edit->deleteTextSelection();
|
edit->deleteTextSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (edit && !edit->getEditStatic())
|
||||||
|
{
|
||||||
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
|
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
|
||||||
{
|
{
|
||||||
std::string text = edit->getTextSelection();
|
std::string text = edit->getTextSelection();
|
||||||
|
@ -591,15 +594,6 @@ namespace MWInput
|
||||||
mMouseWheel = int(arg.z);
|
mMouseWheel = int(arg.z);
|
||||||
|
|
||||||
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
|
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
|
||||||
|
|
||||||
//if the player is reading a book and flicking the mouse wheel
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Book && arg.zrel)
|
|
||||||
{
|
|
||||||
if (arg.zrel < 0)
|
|
||||||
MWBase::Environment::get().getWindowManager()->getBookWindow()->nextPage();
|
|
||||||
else
|
|
||||||
MWBase::Environment::get().getWindowManager()->getBookWindow()->prevPage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMouseLookEnabled)
|
if (mMouseLookEnabled)
|
||||||
|
@ -676,7 +670,7 @@ namespace MWInput
|
||||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
|
||||||
// Not allowed before the magic window is accessible
|
// Not allowed before the magic window is accessible
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
if (!mControlSwitch["playermagic"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
|
@ -691,7 +685,7 @@ namespace MWInput
|
||||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||||
|
|
||||||
// Not allowed before the inventory window is accessible
|
// Not allowed before the inventory window is accessible
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (!mControlSwitch["playerfighting"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
|
@ -831,9 +825,11 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::updateIdleTime(float dt)
|
void InputManager::updateIdleTime(float dt)
|
||||||
{
|
{
|
||||||
|
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
|
.find("fVanityDelay")->getFloat();
|
||||||
if (mTimeIdle >= 0.f)
|
if (mTimeIdle >= 0.f)
|
||||||
mTimeIdle += dt;
|
mTimeIdle += dt;
|
||||||
if (mTimeIdle > 30.f) {
|
if (mTimeIdle > vanityDelay) {
|
||||||
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||||
mTimeIdle = -1.f;
|
mTimeIdle = -1.f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,8 @@ namespace MWMechanics
|
||||||
return mSpells;
|
return mSpells;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects, const std::string &displayName)
|
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects,
|
||||||
|
const std::string &displayName, const std::string& casterHandle)
|
||||||
{
|
{
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||||
|
@ -139,6 +140,7 @@ namespace MWMechanics
|
||||||
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
params.mEffects = effects;
|
params.mEffects = effects;
|
||||||
params.mDisplayName = displayName;
|
params.mDisplayName = displayName;
|
||||||
|
params.mCasterHandle = casterHandle;
|
||||||
|
|
||||||
if (!exists || stack)
|
if (!exists || stack)
|
||||||
mSpells.insert (std::make_pair(id, params));
|
mSpells.insert (std::make_pair(id, params));
|
||||||
|
@ -148,6 +150,12 @@ namespace MWMechanics
|
||||||
mSpellsChanged = true;
|
mSpellsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActiveSpells::removeEffects(const std::string &id)
|
||||||
|
{
|
||||||
|
mSpells.erase(Misc::StringUtils::lowerCase(id));
|
||||||
|
mSpellsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const
|
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const
|
||||||
{
|
{
|
||||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||||
|
@ -164,14 +172,22 @@ namespace MWMechanics
|
||||||
float magnitude = effectIt->mMagnitude;
|
float magnitude = effectIt->mMagnitude;
|
||||||
|
|
||||||
if (magnitude)
|
if (magnitude)
|
||||||
visitor.visit(effectIt->mKey, name, magnitude, remainingTime);
|
visitor.visit(effectIt->mKey, name, it->second.mCasterHandle, magnitude, remainingTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSpells::purgeAll()
|
void ActiveSpells::purgeAll(float chance)
|
||||||
{
|
{
|
||||||
mSpells.clear();
|
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
|
||||||
|
{
|
||||||
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
|
if (roll < chance)
|
||||||
|
mSpells.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
mSpellsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSpells::purgeEffect(short effectId)
|
void ActiveSpells::purgeEffect(short effectId)
|
||||||
|
@ -187,6 +203,6 @@ namespace MWMechanics
|
||||||
effectIt++;
|
effectIt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mSpellsChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace MWMechanics
|
||||||
MWWorld::TimeStamp mTimeStamp;
|
MWWorld::TimeStamp mTimeStamp;
|
||||||
std::string mDisplayName;
|
std::string mDisplayName;
|
||||||
|
|
||||||
// TODO: To handle CASTER_LINKED flag (spell is purged when caster dies),
|
// Handle to the caster that that inflicted this spell on us
|
||||||
// we should probably store a handle to the caster here.
|
std::string mCasterHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::multimap<std::string, ActiveSpellParams > TContainer;
|
typedef std::multimap<std::string, ActiveSpellParams > TContainer;
|
||||||
|
@ -76,14 +76,19 @@ namespace MWMechanics
|
||||||
/// \param stack If false, the spell is not added if one with the same ID exists already.
|
/// \param stack If false, the spell is not added if one with the same ID exists already.
|
||||||
/// \param effects
|
/// \param effects
|
||||||
/// \param displayName Name for display in magic menu.
|
/// \param displayName Name for display in magic menu.
|
||||||
|
/// \param casterHandle
|
||||||
///
|
///
|
||||||
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects, const std::string& displayName);
|
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects,
|
||||||
|
const std::string& displayName, const std::string& casterHandle);
|
||||||
|
|
||||||
/// Remove all active effects with this id
|
/// Removes the active effects from this spell/potion/.. with \a id
|
||||||
|
void removeEffects (const std::string& id);
|
||||||
|
|
||||||
|
/// Remove all active effects with this effect id
|
||||||
void purgeEffect (short effectId);
|
void purgeEffect (short effectId);
|
||||||
|
|
||||||
/// Remove all active effects
|
/// Remove all active effects, if roll succeeds (for each effect)
|
||||||
void purgeAll ();
|
void purgeAll (float chance);
|
||||||
|
|
||||||
bool isSpellActive (std::string id) const;
|
bool isSpellActive (std::string id) const;
|
||||||
///< case insensitive
|
///< case insensitive
|
||||||
|
|
|
@ -46,10 +46,110 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate)
|
||||||
|
{
|
||||||
|
// TODO: remove this check once creatures support inventory store
|
||||||
|
if (ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
|
||||||
|
MWWorld::ContainerStoreIterator item =
|
||||||
|
inv.getSlot(slot);
|
||||||
|
if (item != inv.end())
|
||||||
|
{
|
||||||
|
if (!item->getClass().hasItemHealth(*item))
|
||||||
|
return false;
|
||||||
|
if (item->getCellRef().mCharge == -1)
|
||||||
|
item->getCellRef().mCharge = item->getClass().getItemMaxHealth(*item);
|
||||||
|
|
||||||
|
if (item->getCellRef().mCharge == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
item->getCellRef().mCharge -=
|
||||||
|
std::min(disintegrate,
|
||||||
|
static_cast<float>(item->getCellRef().mCharge));
|
||||||
|
|
||||||
|
if (item->getCellRef().mCharge == 0)
|
||||||
|
{
|
||||||
|
// Will unequip the broken item and try to find a replacement
|
||||||
|
if (ptr.getRefData().getHandle() != "player")
|
||||||
|
inv.autoEquip(ptr);
|
||||||
|
else
|
||||||
|
inv.unequipItem(*item, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class SoulTrap : public MWMechanics::EffectSourceVisitor
|
||||||
|
{
|
||||||
|
MWWorld::Ptr mCreature;
|
||||||
|
MWWorld::Ptr mActor;
|
||||||
|
public:
|
||||||
|
SoulTrap(MWWorld::Ptr trappedCreature)
|
||||||
|
: mCreature(trappedCreature) {}
|
||||||
|
|
||||||
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
|
const std::string& sourceName, const std::string& casterHandle,
|
||||||
|
float magnitude, float remainingTime = -1)
|
||||||
|
{
|
||||||
|
if (key.mId != ESM::MagicEffect::Soultrap)
|
||||||
|
return;
|
||||||
|
if (magnitude <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
MWWorld::Ptr caster = world->searchPtrViaHandle(casterHandle);
|
||||||
|
if (caster.isEmpty() || !caster.getClass().isActor())
|
||||||
|
return;
|
||||||
|
|
||||||
|
static const float fSoulgemMult = world->getStore().get<ESM::GameSetting>().find("fSoulgemMult")->getFloat();
|
||||||
|
|
||||||
|
float creatureSoulValue = mCreature.get<ESM::Creature>()->mBase->mData.mSoul;
|
||||||
|
|
||||||
|
// Use the smallest soulgem that is large enough to hold the soul
|
||||||
|
MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster);
|
||||||
|
MWWorld::ContainerStoreIterator gem = container.end();
|
||||||
|
float gemCapacity = std::numeric_limits<float>().max();
|
||||||
|
std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
|
||||||
|
for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous);
|
||||||
|
it != container.end(); ++it)
|
||||||
|
{
|
||||||
|
const std::string& id = it->getCellRef().mRefID;
|
||||||
|
if (id.size() >= soulgemFilter.size()
|
||||||
|
&& id.substr(0,soulgemFilter.size()) == soulgemFilter)
|
||||||
|
{
|
||||||
|
float thisGemCapacity = it->get<ESM::Miscellaneous>()->mBase->mData.mValue * fSoulgemMult;
|
||||||
|
if (thisGemCapacity >= creatureSoulValue && thisGemCapacity < gemCapacity
|
||||||
|
&& it->getCellRef().mSoul.empty())
|
||||||
|
{
|
||||||
|
gem = it;
|
||||||
|
gemCapacity = thisGemCapacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gem == container.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set the soul on just one of the gems, not the whole stack
|
||||||
|
gem->getContainerStore()->unstack(*gem, caster);
|
||||||
|
gem->getCellRef().mSoul = mCreature.getCellRef().mRefID;
|
||||||
|
|
||||||
|
if (caster.getRefData().getHandle() == "player")
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sSoultrapSuccess}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||||
{
|
{
|
||||||
// magic effects
|
// magic effects
|
||||||
|
@ -178,7 +278,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
// the actor is sleeping, restore health and magicka
|
// the actor is sleeping, restore health and magicka
|
||||||
|
|
||||||
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
|
bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0;
|
||||||
|
|
||||||
DynamicStat<float> health = stats.getHealth();
|
DynamicStat<float> health = stats.getHealth();
|
||||||
health.setCurrent (health.getCurrent() + 0.1 * endurance);
|
health.setCurrent (health.getCurrent() + 0.1 * endurance);
|
||||||
|
@ -217,7 +317,7 @@ namespace MWMechanics
|
||||||
// attributes
|
// attributes
|
||||||
for(int i = 0;i < ESM::Attribute::Length;++i)
|
for(int i = 0;i < ESM::Attribute::Length;++i)
|
||||||
{
|
{
|
||||||
Stat<int> stat = creatureStats.getAttribute(i);
|
AttributeValue stat = creatureStats.getAttribute(i);
|
||||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
|
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
|
||||||
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude -
|
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude -
|
||||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude);
|
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude);
|
||||||
|
@ -229,18 +329,45 @@ namespace MWMechanics
|
||||||
for(int i = 0;i < 3;++i)
|
for(int i = 0;i < 3;++i)
|
||||||
{
|
{
|
||||||
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
||||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyHealth+i)).mMagnitude -
|
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).mMagnitude -
|
||||||
effects.get(EffectKey(ESM::MagicEffect::DrainHealth+i)).mMagnitude);
|
effects.get(ESM::MagicEffect::DrainHealth+i).mMagnitude);
|
||||||
|
|
||||||
|
|
||||||
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).mMagnitude
|
||||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
- creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).mMagnitude
|
||||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude;
|
- creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).mMagnitude;
|
||||||
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
||||||
|
|
||||||
creatureStats.setDynamic(i, stat);
|
creatureStats.setDynamic(i, stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply disintegration (reduces item health)
|
||||||
|
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude;
|
||||||
|
if (disintegrateWeapon > 0)
|
||||||
|
disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration);
|
||||||
|
float disintegrateArmor = effects.get(ESM::MagicEffect::DisintegrateArmor).mMagnitude;
|
||||||
|
if (disintegrateArmor > 0)
|
||||||
|
{
|
||||||
|
// According to UESP
|
||||||
|
int priorities[] = {
|
||||||
|
MWWorld::InventoryStore::Slot_CarriedLeft,
|
||||||
|
MWWorld::InventoryStore::Slot_Cuirass,
|
||||||
|
MWWorld::InventoryStore::Slot_LeftPauldron,
|
||||||
|
MWWorld::InventoryStore::Slot_RightPauldron,
|
||||||
|
MWWorld::InventoryStore::Slot_LeftGauntlet,
|
||||||
|
MWWorld::InventoryStore::Slot_RightGauntlet,
|
||||||
|
MWWorld::InventoryStore::Slot_Helmet,
|
||||||
|
MWWorld::InventoryStore::Slot_Greaves,
|
||||||
|
MWWorld::InventoryStore::Slot_Boots
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<sizeof(priorities)/sizeof(int); ++i)
|
||||||
|
{
|
||||||
|
if (disintegrateSlot(ptr, priorities[i], disintegrateArmor*duration))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply damage ticks
|
// Apply damage ticks
|
||||||
int damageEffects[] = {
|
int damageEffects[] = {
|
||||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||||
|
@ -250,7 +377,7 @@ namespace MWMechanics
|
||||||
DynamicStat<float> health = creatureStats.getHealth();
|
DynamicStat<float> health = creatureStats.getHealth();
|
||||||
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
||||||
{
|
{
|
||||||
float magnitude = creatureStats.getMagicEffects().get(EffectKey(damageEffects[i])).mMagnitude;
|
float magnitude = creatureStats.getMagicEffects().get(damageEffects[i]).mMagnitude;
|
||||||
|
|
||||||
if (damageEffects[i] == ESM::MagicEffect::SunDamage)
|
if (damageEffects[i] == ESM::MagicEffect::SunDamage)
|
||||||
{
|
{
|
||||||
|
@ -281,30 +408,32 @@ namespace MWMechanics
|
||||||
static std::map<int, std::string> boundItemsMap;
|
static std::map<int, std::string> boundItemsMap;
|
||||||
if (boundItemsMap.empty())
|
if (boundItemsMap.empty())
|
||||||
{
|
{
|
||||||
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "battle_axe";
|
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "sMagicBoundBattleAxeID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundBoots] = "boots";
|
boundItemsMap[ESM::MagicEffect::BoundBoots] = "sMagicBoundBootsID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "cuirass";
|
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "sMagicBoundCuirassID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundDagger] = "dagger";
|
boundItemsMap[ESM::MagicEffect::BoundDagger] = "sMagicBoundDaggerID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundGloves] = "gauntlet"; // Note: needs both _left and _right variants, see below
|
boundItemsMap[ESM::MagicEffect::BoundGloves] = "sMagicBoundLeftGauntletID"; // Note: needs RightGauntlet variant too (see below)
|
||||||
boundItemsMap[ESM::MagicEffect::BoundHelm] = "helm";
|
boundItemsMap[ESM::MagicEffect::BoundHelm] = "sMagicBoundHelmID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "longbow";
|
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "sMagicBoundLongbowID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "longsword";
|
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "sMagicBoundLongswordID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundMace] = "mace";
|
boundItemsMap[ESM::MagicEffect::BoundMace] = "sMagicBoundMaceID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundShield] = "shield";
|
boundItemsMap[ESM::MagicEffect::BoundShield] = "sMagicBoundShieldID";
|
||||||
boundItemsMap[ESM::MagicEffect::BoundSpear] = "spear";
|
boundItemsMap[ESM::MagicEffect::BoundSpear] = "sMagicBoundSpearID";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
|
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
|
||||||
{
|
{
|
||||||
bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end();
|
bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end();
|
||||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||||
if (found != (magnitude > 0))
|
if (found != (magnitude > 0))
|
||||||
{
|
{
|
||||||
std::string item = "bound_" + it->second;
|
std::string itemGmst = it->second;
|
||||||
|
std::string item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
itemGmst)->getString();
|
||||||
if (it->first == ESM::MagicEffect::BoundGloves)
|
if (it->first == ESM::MagicEffect::BoundGloves)
|
||||||
{
|
{
|
||||||
adjustBoundItem(item + "_left", magnitude > 0, ptr);
|
adjustBoundItem("sMagicBoundLeftGauntletID", magnitude > 0, ptr);
|
||||||
adjustBoundItem(item + "_right", magnitude > 0, ptr);
|
adjustBoundItem("sMagicBoundRightGauntletID", magnitude > 0, ptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
adjustBoundItem(item, magnitude > 0, ptr);
|
adjustBoundItem(item, magnitude > 0, ptr);
|
||||||
|
@ -320,32 +449,34 @@ namespace MWMechanics
|
||||||
static std::map<int, std::string> summonMap;
|
static std::map<int, std::string> summonMap;
|
||||||
if (summonMap.empty())
|
if (summonMap.empty())
|
||||||
{
|
{
|
||||||
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "ancestor_ghost_summon";
|
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "sMagicAncestralGhostID";
|
||||||
summonMap[ESM::MagicEffect::SummonBear] = "BM_bear_black_summon";
|
summonMap[ESM::MagicEffect::SummonBonelord] = "sMagicBonelordID";
|
||||||
summonMap[ESM::MagicEffect::SummonBonelord] = "bonelord_summon";
|
summonMap[ESM::MagicEffect::SummonBonewalker] = "sMagicLeastBonewalkerID";
|
||||||
summonMap[ESM::MagicEffect::SummonBonewalker] = "bonewalker_summon";
|
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "sMagicCenturionSphereID";
|
||||||
summonMap[ESM::MagicEffect::SummonBonewolf] = "BM_wolf_bone_summon";
|
summonMap[ESM::MagicEffect::SummonClannfear] = "sMagicClannfearID";
|
||||||
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "centurion_sphere_summon";
|
summonMap[ESM::MagicEffect::SummonDaedroth] = "sMagicDaedrothID";
|
||||||
summonMap[ESM::MagicEffect::SummonClannfear] = "clannfear_summon";
|
summonMap[ESM::MagicEffect::SummonDremora] = "sMagicDremoraID";
|
||||||
summonMap[ESM::MagicEffect::SummonDaedroth] = "daedroth_summon";
|
summonMap[ESM::MagicEffect::SummonFabricant] = "sMagicFabricantID";
|
||||||
summonMap[ESM::MagicEffect::SummonDremora] = "dremora_summon";
|
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "sMagicFlameAtronachID";
|
||||||
summonMap[ESM::MagicEffect::SummonFabricant] = "fabricant_summon";
|
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "sMagicFrostAtronachID";
|
||||||
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "atronach_flame_summon";
|
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "sMagicGoldenSaintID";
|
||||||
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "atronach_frost_summon";
|
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "sMagicGreaterBonewalkerID";
|
||||||
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "golden saint_summon";
|
summonMap[ESM::MagicEffect::SummonHunger] = "sMagicHungerID";
|
||||||
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "bonewalker_greater_summ";
|
summonMap[ESM::MagicEffect::SummonScamp] = "sMagicScampID";
|
||||||
summonMap[ESM::MagicEffect::SummonHunger] = "hunger_summon";
|
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "sMagicSkeletalMinionID";
|
||||||
summonMap[ESM::MagicEffect::SummonScamp] = "scamp_summon";
|
summonMap[ESM::MagicEffect::SummonStormAtronach] = "sMagicStormAtronachID";
|
||||||
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "skeleton_summon";
|
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "sMagicWingedTwilightID";
|
||||||
summonMap[ESM::MagicEffect::SummonStormAtronach] = "atronach_storm_summon";
|
summonMap[ESM::MagicEffect::SummonWolf] = "sMagicCreature01ID";
|
||||||
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "winged twilight_summon";
|
summonMap[ESM::MagicEffect::SummonBear] = "sMagicCreature02ID";
|
||||||
summonMap[ESM::MagicEffect::SummonWolf] = "BM_wolf_grey_summon";
|
summonMap[ESM::MagicEffect::SummonBonewolf] = "sMagicCreature03ID";
|
||||||
|
summonMap[ESM::MagicEffect::SummonCreature04] = "sMagicCreature04ID";
|
||||||
|
summonMap[ESM::MagicEffect::SummonCreature05] = "sMagicCreature05ID";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it)
|
for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it)
|
||||||
{
|
{
|
||||||
bool found = creatureStats.mSummonedCreatures.find(it->first) != creatureStats.mSummonedCreatures.end();
|
bool found = creatureStats.mSummonedCreatures.find(it->first) != creatureStats.mSummonedCreatures.end();
|
||||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||||
if (found != (magnitude > 0))
|
if (found != (magnitude > 0))
|
||||||
{
|
{
|
||||||
if (magnitude > 0)
|
if (magnitude > 0)
|
||||||
|
@ -362,15 +493,20 @@ namespace MWMechanics
|
||||||
ipos.rot[1] = 0;
|
ipos.rot[1] = 0;
|
||||||
ipos.rot[2] = 0;
|
ipos.rot[2] = 0;
|
||||||
|
|
||||||
|
std::string creatureID =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
|
||||||
|
|
||||||
|
if (!creatureID.empty())
|
||||||
|
{
|
||||||
MWWorld::CellStore* store = ptr.getCell();
|
MWWorld::CellStore* store = ptr.getCell();
|
||||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), it->second, 1);
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
||||||
ref.getPtr().getCellRef().mPos = ipos;
|
ref.getPtr().getCellRef().mPos = ipos;
|
||||||
|
|
||||||
// TODO: Add AI to follow player and fight for him
|
// TODO: Add AI to follow player and fight for him
|
||||||
|
|
||||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -396,7 +532,7 @@ namespace MWMechanics
|
||||||
// skills
|
// skills
|
||||||
for(int i = 0;i < ESM::Skill::Length;++i)
|
for(int i = 0;i < ESM::Skill::Length;++i)
|
||||||
{
|
{
|
||||||
Stat<float>& skill = npcStats.getSkill(i);
|
SkillValue& skill = npcStats.getSkill(i);
|
||||||
skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).mMagnitude -
|
skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).mMagnitude -
|
||||||
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).mMagnitude -
|
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).mMagnitude -
|
||||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).mMagnitude);
|
effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).mMagnitude);
|
||||||
|
@ -448,36 +584,57 @@ namespace MWMechanics
|
||||||
/**
|
/**
|
||||||
* Automatically equip NPCs torches at night and unequip them at day
|
* Automatically equip NPCs torches at night and unequip them at day
|
||||||
*/
|
*/
|
||||||
if (!isPlayer && !MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile())
|
if (!isPlayer)
|
||||||
{
|
{
|
||||||
if (mTorchPtr.isEmpty())
|
MWWorld::ContainerStoreIterator torch = inventoryStore.end();
|
||||||
|
for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it)
|
||||||
{
|
{
|
||||||
mTorchPtr = inventoryStore.search("torch_infinite_time");
|
if (it->getTypeName() == typeid(ESM::Light).name())
|
||||||
|
{
|
||||||
|
torch = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWorld()->isNight())
|
if (MWBase::Environment::get().getWorld()->isDark())
|
||||||
{
|
{
|
||||||
|
if (torch != inventoryStore.end())
|
||||||
|
{
|
||||||
|
if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile())
|
||||||
|
{
|
||||||
|
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
|
||||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||||
{
|
|
||||||
inventoryStore.unequipItem(*heldIter, ptr);
|
inventoryStore.unequipItem(*heldIter, ptr);
|
||||||
|
|
||||||
|
// Also unequip twohanded weapons which conflict with anything in CarriedLeft
|
||||||
|
if (torch->getClass().canBeEquipped(*torch, ptr).first == 3)
|
||||||
|
inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr);
|
||||||
}
|
}
|
||||||
else if (heldIter == inventoryStore.end() && !mTorchPtr.isEmpty())
|
|
||||||
|
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
|
||||||
|
// If we have a torch and can equip it (left slot free, no
|
||||||
|
// twohanded weapon in right slot), then equip it now.
|
||||||
|
if (heldIter == inventoryStore.end()
|
||||||
|
&& torch->getClass().canBeEquipped(*torch, ptr).first == 1)
|
||||||
{
|
{
|
||||||
heldIter = inventoryStore.add(mTorchPtr, ptr);
|
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
||||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, heldIter, ptr);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name())
|
if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name())
|
||||||
{
|
{
|
||||||
inventoryStore.unequipItem(*heldIter, ptr);
|
// At day, unequip lights and auto equip shields or other suitable items
|
||||||
inventoryStore.add(*heldIter, ptr);
|
// (Note: autoEquip will ignore lights)
|
||||||
inventoryStore.autoEquip(ptr);
|
inventoryStore.autoEquip(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
|
||||||
//If holding a light...
|
//If holding a light...
|
||||||
if(heldIter.getType() == MWWorld::ContainerStore::Type_Light)
|
if(heldIter.getType() == MWWorld::ContainerStore::Type_Light)
|
||||||
{
|
{
|
||||||
|
@ -516,6 +673,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
Actors::Actors() {}
|
Actors::Actors() {}
|
||||||
|
|
||||||
|
Actors::~Actors()
|
||||||
|
{
|
||||||
|
PtrControllerMap::iterator it(mActors.begin());
|
||||||
|
for (; it != mActors.end(); ++it)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
it->second = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
// erase previous death events since we are currently only tracking them while in an active cell
|
// erase previous death events since we are currently only tracking them while in an active cell
|
||||||
|
@ -609,10 +776,23 @@ namespace MWMechanics
|
||||||
|
|
||||||
iter->second->kill();
|
iter->second->kill();
|
||||||
|
|
||||||
|
// Apply soultrap
|
||||||
|
if (iter->first.getTypeName() == typeid(ESM::Creature).name())
|
||||||
|
{
|
||||||
|
SoulTrap soulTrap (iter->first);
|
||||||
|
stats.getActiveSpells().visitEffectSources(soulTrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset magic effects and recalculate derived effects
|
||||||
|
// One case where we need this is to make sure bound items are removed upon death
|
||||||
|
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||||
|
calculateCreatureStatModifiers(iter->first, 0);
|
||||||
|
|
||||||
++mDeathCount[cls.getId(iter->first)];
|
++mDeathCount[cls.getId(iter->first)];
|
||||||
|
|
||||||
if(cls.isEssential(iter->first))
|
if(cls.isEssential(iter->first))
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,9 +806,14 @@ namespace MWMechanics
|
||||||
iter->second->updateContinuousVfx();
|
iter->second->updateContinuousVfx();
|
||||||
|
|
||||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||||
|
{
|
||||||
|
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
|
||||||
|
ESM::MagicEffect::Paralyze).mMagnitude > 0)
|
||||||
|
iter->second->skipAnim();
|
||||||
iter->second->update(duration);
|
iter->second->update(duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void Actors::restoreDynamicStats()
|
void Actors::restoreDynamicStats()
|
||||||
{
|
{
|
||||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace MWMechanics
|
||||||
PtrControllerMap mActors;
|
PtrControllerMap mActors;
|
||||||
|
|
||||||
std::map<std::string, int> mDeathCount;
|
std::map<std::string, int> mDeathCount;
|
||||||
MWWorld::Ptr mTorchPtr;
|
|
||||||
|
|
||||||
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
||||||
|
|
||||||
|
@ -49,6 +48,7 @@ namespace MWMechanics
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Actors();
|
Actors();
|
||||||
|
~Actors();
|
||||||
|
|
||||||
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
|
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
|
||||||
/// paused we may want to do it manually (after equipping permanent enchantment)
|
/// paused we may want to do it manually (after equipping permanent enchantment)
|
||||||
|
|
|
@ -91,6 +91,8 @@ namespace MWMechanics
|
||||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||||
|
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
|
|
||||||
|
// TODO: use movement settings instead of rotating directly
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
|
||||||
|
@ -105,6 +107,7 @@ namespace MWMechanics
|
||||||
float directionResult = sqrt(directionX * directionX + directionY * directionY);
|
float directionResult = sqrt(directionX * directionX + directionY * directionY);
|
||||||
|
|
||||||
zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees();
|
zAngle = Ogre::Radian( acos(directionY / directionResult) * sgn(asin(directionX / directionResult)) ).valueDegrees();
|
||||||
|
// TODO: use movement settings instead of rotating directly
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
|
|
||||||
mPathFinder.clearPath();
|
mPathFinder.clearPath();
|
||||||
|
|
|
@ -161,6 +161,7 @@ namespace MWMechanics
|
||||||
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
||||||
{
|
{
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
|
// TODO: use movement settings instead of rotating directly
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
mMaxDist = 470;
|
mMaxDist = 470;
|
||||||
|
|
|
@ -97,6 +97,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
|
// TODO: use movement settings instead of rotating directly
|
||||||
world->rotateObject(actor, 0, 0, zAngle, false);
|
world->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
movement.mPosition[1] = 1;
|
movement.mPosition[1] = 1;
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,7 @@ namespace MWMechanics
|
||||||
if(mWalking)
|
if(mWalking)
|
||||||
{
|
{
|
||||||
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
|
// TODO: use movement settings instead of rotating directly
|
||||||
world->rotateObject(actor, 0, 0, zAngle, false);
|
world->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/actionequip.hpp"
|
|
||||||
#include "../mwworld/actiontake.hpp"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -1063,6 +1061,8 @@ void CharacterController::update(float duration)
|
||||||
|
|
||||||
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
||||||
|
|
||||||
|
if (!mSkipAnim)
|
||||||
|
{
|
||||||
if(mHitState != CharState_KnockDown)
|
if(mHitState != CharState_KnockDown)
|
||||||
{
|
{
|
||||||
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
|
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
|
||||||
|
@ -1072,6 +1072,8 @@ void CharacterController::update(float duration)
|
||||||
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
||||||
|
|
||||||
world->queueMovement(mPtr, vec);
|
world->queueMovement(mPtr, vec);
|
||||||
|
}
|
||||||
|
|
||||||
movement = vec;
|
movement = vec;
|
||||||
}
|
}
|
||||||
else if(cls.getCreatureStats(mPtr).isDead())
|
else if(cls.getCreatureStats(mPtr).isDead())
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace MWMechanics
|
||||||
- gmst.find ("fFatigueMult")->getFloat() * (1-normalised);
|
- gmst.find ("fFatigueMult")->getFloat() * (1-normalised);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Stat<int> &CreatureStats::getAttribute(int index) const
|
const AttributeValue &CreatureStats::getAttribute(int index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index > 7) {
|
if (index < 0 || index > 7) {
|
||||||
throw std::runtime_error("attribute index is out of range");
|
throw std::runtime_error("attribute index is out of range");
|
||||||
|
@ -158,20 +158,20 @@ namespace MWMechanics
|
||||||
|
|
||||||
void CreatureStats::setAttribute(int index, int base)
|
void CreatureStats::setAttribute(int index, int base)
|
||||||
{
|
{
|
||||||
MWMechanics::Stat<int> current = getAttribute(index);
|
AttributeValue current = getAttribute(index);
|
||||||
current.setBase(base);
|
current.setBase(base);
|
||||||
setAttribute(index, current);
|
setAttribute(index, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureStats::setAttribute(int index, const Stat<int> &value)
|
void CreatureStats::setAttribute(int index, const AttributeValue &value)
|
||||||
{
|
{
|
||||||
if (index < 0 || index > 7) {
|
if (index < 0 || index > 7) {
|
||||||
throw std::runtime_error("attribute index is out of range");
|
throw std::runtime_error("attribute index is out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
const Stat<int>& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
||||||
|
|
||||||
if (value.getModified() != currentValue.getModified())
|
if (value != currentValue)
|
||||||
{
|
{
|
||||||
if (index != ESM::Attribute::Luck
|
if (index != ESM::Attribute::Luck
|
||||||
&& index != ESM::Attribute::Personality
|
&& index != ESM::Attribute::Personality
|
||||||
|
@ -228,8 +228,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void CreatureStats::setMagicEffects(const MagicEffects &effects)
|
void CreatureStats::setMagicEffects(const MagicEffects &effects)
|
||||||
{
|
{
|
||||||
if (effects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude
|
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude
|
||||||
!= mMagicEffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude)
|
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude)
|
||||||
mRecalcDynamicStats = true;
|
mRecalcDynamicStats = true;
|
||||||
|
|
||||||
mMagicEffects = effects;
|
mMagicEffects = effects;
|
||||||
|
@ -266,8 +266,10 @@ namespace MWMechanics
|
||||||
if (mDead)
|
if (mDead)
|
||||||
{
|
{
|
||||||
if (mDynamic[0].getCurrent()<1)
|
if (mDynamic[0].getCurrent()<1)
|
||||||
mDynamic[0].setCurrent (1);
|
{
|
||||||
|
mDynamic[0].setModified(mDynamic[0].getModified(), 1);
|
||||||
|
mDynamic[0].setCurrent(1);
|
||||||
|
}
|
||||||
if (mDynamic[0].getCurrent()>=1)
|
if (mDynamic[0].getCurrent()>=1)
|
||||||
mDead = false;
|
mDead = false;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +345,7 @@ namespace MWMechanics
|
||||||
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||||
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||||
evasion *= getFatigueTerm();
|
evasion *= getFatigueTerm();
|
||||||
evasion += mMagicEffects.get(EffectKey(ESM::MagicEffect::Sanctuary)).mMagnitude;
|
evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).mMagnitude;
|
||||||
|
|
||||||
return evasion;
|
return evasion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MWMechanics
|
||||||
///
|
///
|
||||||
class CreatureStats
|
class CreatureStats
|
||||||
{
|
{
|
||||||
Stat<int> mAttributes[8];
|
AttributeValue mAttributes[8];
|
||||||
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
||||||
int mLevel;
|
int mLevel;
|
||||||
Spells mSpells;
|
Spells mSpells;
|
||||||
|
@ -49,7 +49,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool mIsWerewolf;
|
bool mIsWerewolf;
|
||||||
Stat<int> mWerewolfAttributes[8];
|
AttributeValue mWerewolfAttributes[8];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CreatureStats();
|
CreatureStats();
|
||||||
|
@ -65,7 +65,7 @@ namespace MWMechanics
|
||||||
bool canUsePower (const std::string& power) const;
|
bool canUsePower (const std::string& power) const;
|
||||||
void usePower (const std::string& power);
|
void usePower (const std::string& power);
|
||||||
|
|
||||||
const Stat<int> & getAttribute(int index) const;
|
const AttributeValue & getAttribute(int index) const;
|
||||||
|
|
||||||
const DynamicStat<float> & getHealth() const;
|
const DynamicStat<float> & getHealth() const;
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
MagicEffects & getMagicEffects();
|
MagicEffects & getMagicEffects();
|
||||||
|
|
||||||
void setAttribute(int index, const Stat<int> &value);
|
void setAttribute(int index, const AttributeValue &value);
|
||||||
// Shortcut to set only the base
|
// Shortcut to set only the base
|
||||||
void setAttribute(int index, int base);
|
void setAttribute(int index, int base);
|
||||||
|
|
||||||
|
|
53
apps/openmw/mwmechanics/disease.hpp
Normal file
53
apps/openmw/mwmechanics/disease.hpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef OPENMW_MECHANICS_DISEASE_H
|
||||||
|
#define OPENMW_MECHANICS_DISEASE_H
|
||||||
|
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwmechanics/spells.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Call when \a actor has got in contact with \a carrier (e.g. hit by him, or loots him)
|
||||||
|
inline void diseaseContact (MWWorld::Ptr actor, MWWorld::Ptr carrier)
|
||||||
|
{
|
||||||
|
if (!carrier.getClass().isActor())
|
||||||
|
return;
|
||||||
|
|
||||||
|
float fDiseaseXferChance =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
|
"fDiseaseXferChance")->getFloat();
|
||||||
|
|
||||||
|
Spells& spells = carrier.getClass().getCreatureStats(carrier).getSpells();
|
||||||
|
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(it->first);
|
||||||
|
if (spell->mData.mType == ESM::Spell::ST_Disease
|
||||||
|
|| spell->mData.mType == ESM::Spell::ST_Blight)
|
||||||
|
{
|
||||||
|
float roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
|
if (roll < fDiseaseXferChance)
|
||||||
|
{
|
||||||
|
// Contracted disease!
|
||||||
|
actor.getClass().getCreatureStats(actor).getSpells().add(it->first);
|
||||||
|
|
||||||
|
if (actor.getRefData().getHandle() == "player")
|
||||||
|
{
|
||||||
|
std::string msg = "sMagicContractDisease";
|
||||||
|
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->getString();
|
||||||
|
if (msg.find("%s") != std::string::npos)
|
||||||
|
msg.replace(msg.find("%s"), 2, spell->mName);
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -56,7 +56,8 @@ namespace MWMechanics
|
||||||
struct EffectSourceVisitor
|
struct EffectSourceVisitor
|
||||||
{
|
{
|
||||||
virtual void visit (MWMechanics::EffectKey key,
|
virtual void visit (MWMechanics::EffectKey key,
|
||||||
const std::string& sourceName, float magnitude, float remainingTime = -1) = 0;
|
const std::string& sourceName, const std::string& casterHandle,
|
||||||
|
float magnitude, float remainingTime = -1) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Effects currently affecting a NPC or creature
|
/// \brief Effects currently affecting a NPC or creature
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "spellcasting.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void MechanicsManager::buildPlayer()
|
void MechanicsManager::buildPlayer()
|
||||||
|
@ -123,6 +125,19 @@ namespace MWMechanics
|
||||||
npcStats.getSkill (index).setBase (
|
npcStats.getSkill (index).setBase (
|
||||||
npcStats.getSkill (index).getBase() + bonus);
|
npcStats.getSkill (index).getBase() + bonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i==1)
|
||||||
|
{
|
||||||
|
// Major skill - add starting spells for this skill if existing
|
||||||
|
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
||||||
|
for (; it != store.get<ESM::Spell>().end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mData.mFlags & ESM::Spell::F_PCStart
|
||||||
|
&& spellSchoolToSkill(getSpellSchool(&*it, ptr)) == index)
|
||||||
|
creatureStats.getSpells().add(it->mId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,10 +499,10 @@ namespace MWMechanics
|
||||||
// otherwise one would get different prices when exiting and re-entering the dialogue window...
|
// otherwise one would get different prices when exiting and re-entering the dialogue window...
|
||||||
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
||||||
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100));
|
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100));
|
||||||
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||||
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||||
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||||
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||||
float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||||
float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ void MWMechanics::NpcStats::setMovementFlag (Flag flag, bool state)
|
||||||
mMovementFlags &= ~flag;
|
mMovementFlags &= ~flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) const
|
const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const
|
||||||
{
|
{
|
||||||
if (index<0 || index>=ESM::Skill::Length)
|
if (index<0 || index>=ESM::Skill::Length)
|
||||||
throw std::runtime_error ("skill index out of range");
|
throw std::runtime_error ("skill index out of range");
|
||||||
|
@ -92,7 +92,7 @@ const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) cons
|
||||||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index)
|
MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
||||||
{
|
{
|
||||||
if (index<0 || index>=ESM::Skill::Length)
|
if (index<0 || index>=ESM::Skill::Length)
|
||||||
throw std::runtime_error ("skill index out of range");
|
throw std::runtime_error ("skill index out of range");
|
||||||
|
@ -197,34 +197,25 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
|
||||||
if(mIsWerewolf)
|
if(mIsWerewolf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float base = getSkill (skillIndex).getBase();
|
MWMechanics::SkillValue value = getSkill (skillIndex);
|
||||||
|
|
||||||
int level = static_cast<int> (base);
|
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType));
|
||||||
|
|
||||||
base += getSkillGain (skillIndex, class_, usageType);
|
if (value.getProgress()>=1)
|
||||||
|
|
||||||
if (static_cast<int> (base)!=level)
|
|
||||||
{
|
{
|
||||||
// skill leveled up
|
// skill leveled up
|
||||||
increaseSkill(skillIndex, class_, false);
|
increaseSkill(skillIndex, class_, false);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
getSkill (skillIndex).setBase (base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
|
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
|
||||||
{
|
{
|
||||||
float base = getSkill (skillIndex).getBase();
|
int base = getSkill (skillIndex).getBase();
|
||||||
|
|
||||||
int level = static_cast<int> (base);
|
if (base >= 100)
|
||||||
|
|
||||||
if (level >= 100)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (preserveProgress)
|
|
||||||
base += 1;
|
base += 1;
|
||||||
else
|
|
||||||
base = level+1;
|
|
||||||
|
|
||||||
// if this is a major or minor skill of the class, increase level progress
|
// if this is a major or minor skill of the class, increase level progress
|
||||||
bool levelProgress = false;
|
bool levelProgress = false;
|
||||||
|
@ -260,6 +251,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
||||||
}
|
}
|
||||||
|
|
||||||
getSkill (skillIndex).setBase (base);
|
getSkill (skillIndex).setBase (base);
|
||||||
|
if (!preserveProgress)
|
||||||
|
getSkill(skillIndex).setProgress(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::NpcStats::getLevelProgress () const
|
int MWMechanics::NpcStats::getLevelProgress () const
|
||||||
|
@ -387,7 +380,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
||||||
// Oh, Bethesda. It's "Intelligence".
|
// Oh, Bethesda. It's "Intelligence".
|
||||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||||
ESM::Attribute::sAttributeNames[i]);
|
ESM::Attribute::sAttributeNames[i]);
|
||||||
mWerewolfAttributes[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
||||||
|
@ -401,7 +394,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
||||||
// "Mercantile"! >_<
|
// "Mercantile"! >_<
|
||||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||||
ESM::Skill::sSkillNames[i]);
|
ESM::Skill::sSkillNames[i]);
|
||||||
mWerewolfSkill[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mIsWerewolf = set;
|
mIsWerewolf = set;
|
||||||
|
|
|
@ -45,8 +45,8 @@ namespace MWMechanics
|
||||||
DrawState_ mDrawState;
|
DrawState_ mDrawState;
|
||||||
int mDisposition;
|
int mDisposition;
|
||||||
unsigned int mMovementFlags;
|
unsigned int mMovementFlags;
|
||||||
Stat<float> mSkill[27];
|
SkillValue mSkill[27];
|
||||||
Stat<float> mWerewolfSkill[27];
|
SkillValue mWerewolfSkill[27];
|
||||||
int mBounty;
|
int mBounty;
|
||||||
std::set<std::string> mExpelled;
|
std::set<std::string> mExpelled;
|
||||||
std::map<std::string, int> mFactionReputation;
|
std::map<std::string, int> mFactionReputation;
|
||||||
|
@ -94,8 +94,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
void setMovementFlag (Flag flag, bool state);
|
void setMovementFlag (Flag flag, bool state);
|
||||||
|
|
||||||
const Stat<float>& getSkill (int index) const;
|
const SkillValue& getSkill (int index) const;
|
||||||
Stat<float>& getSkill (int index);
|
SkillValue& getSkill (int index);
|
||||||
|
|
||||||
const std::map<std::string, int>& getFactionRanks() const;
|
const std::map<std::string, int>& getFactionRanks() const;
|
||||||
std::map<std::string, int>& getFactionRanks();
|
std::map<std::string, int>& getFactionRanks();
|
||||||
|
|
|
@ -14,6 +14,16 @@ Objects::Objects()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Objects::~Objects()
|
||||||
|
{
|
||||||
|
PtrControllerMap::iterator it(mObjects.begin());
|
||||||
|
for (; it != mObjects.end();++it)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
it->second = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Objects::addObject(const MWWorld::Ptr& ptr)
|
void Objects::addObject(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
removeObject(ptr);
|
removeObject(ptr);
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Objects();
|
Objects();
|
||||||
|
~Objects();
|
||||||
|
|
||||||
void addObject (const MWWorld::Ptr& ptr);
|
void addObject (const MWWorld::Ptr& ptr);
|
||||||
///< Register an animated object
|
///< Register an animated object
|
||||||
|
|
|
@ -24,21 +24,13 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
||||||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||||
mTool.get<ESM::Repair>();
|
mTool.get<ESM::Repair>();
|
||||||
|
|
||||||
|
// unstack tool if required
|
||||||
|
player.getClass().getContainerStore(player).unstack(mTool, player);
|
||||||
|
|
||||||
// reduce number of uses left
|
// reduce number of uses left
|
||||||
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
|
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
|
||||||
mTool.getCellRef().mCharge = uses-1;
|
mTool.getCellRef().mCharge = uses-1;
|
||||||
|
|
||||||
// unstack tool if required
|
|
||||||
if (mTool.getRefData().getCount() > 1 && uses == ref->mBase->mData.mUses)
|
|
||||||
{
|
|
||||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
|
||||||
MWWorld::ContainerStoreIterator it = store.add(mTool, player);
|
|
||||||
it->getRefData().setCount(mTool.getRefData().getCount()-1);
|
|
||||||
it->getCellRef().mCharge = -1;
|
|
||||||
|
|
||||||
mTool.getRefData().setCount(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||||
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
|
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/actionteleport.hpp"
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
|
@ -66,6 +68,12 @@ namespace MWMechanics
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
||||||
effectIt->mEffectID);
|
effectIt->mEffectID);
|
||||||
|
|
||||||
|
// If player is healing someone, show the target's HP bar
|
||||||
|
if (caster.getRefData().getHandle() == "player" && target != caster
|
||||||
|
&& effectIt->mEffectID == ESM::MagicEffect::RestoreHealth
|
||||||
|
&& target.getClass().isActor())
|
||||||
|
MWBase::Environment::get().getWindowManager()->setEnemy(target);
|
||||||
|
|
||||||
float magnitudeMult = 1;
|
float magnitudeMult = 1;
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && target.getClass().isActor())
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && target.getClass().isActor())
|
||||||
{
|
{
|
||||||
|
@ -133,7 +141,8 @@ namespace MWMechanics
|
||||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||||
magnitude *= magnitudeMult;
|
magnitude *= magnitudeMult;
|
||||||
|
|
||||||
if (target.getClass().isActor() && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||||
|
if (target.getClass().isActor() && hasDuration)
|
||||||
{
|
{
|
||||||
ActiveSpells::Effect effect;
|
ActiveSpells::Effect effect;
|
||||||
effect.mKey = MWMechanics::EffectKey(*effectIt);
|
effect.mKey = MWMechanics::EffectKey(*effectIt);
|
||||||
|
@ -152,12 +161,23 @@ namespace MWMechanics
|
||||||
ActiveSpells::Effect effect_ = effect;
|
ActiveSpells::Effect effect_ = effect;
|
||||||
effect_.mMagnitude *= -1;
|
effect_.mMagnitude *= -1;
|
||||||
effects.push_back(effect_);
|
effects.push_back(effect_);
|
||||||
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, effects, mSourceName);
|
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
||||||
|
effects, mSourceName, caster.getRefData().getHandle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
applyInstantEffect(target, effectIt->mEffectID, magnitude);
|
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||||
|
|
||||||
|
// HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent.
|
||||||
|
// This was probably just done to have the effect visible in the magic menu for a while
|
||||||
|
// to notify the player they've been damaged?
|
||||||
|
if (effectIt->mEffectID == ESM::MagicEffect::DamageAttribute
|
||||||
|
|| effectIt->mEffectID == ESM::MagicEffect::DamageSkill
|
||||||
|
|| effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute
|
||||||
|
|| effectIt->mEffectID == ESM::MagicEffect::RestoreSkill
|
||||||
|
)
|
||||||
|
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||||
|
|
||||||
if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)
|
if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)
|
||||||
{
|
{
|
||||||
|
@ -196,11 +216,13 @@ namespace MWMechanics
|
||||||
inflict(caster, target, reflectedEffects, range, true);
|
inflict(caster, target, reflectedEffects, range, true);
|
||||||
|
|
||||||
if (appliedLastingEffects.size())
|
if (appliedLastingEffects.size())
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, mSourceName);
|
target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects,
|
||||||
|
mSourceName, caster.getRefData().getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, short effectId, float magnitude)
|
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, MWMechanics::EffectKey effect, float magnitude)
|
||||||
{
|
{
|
||||||
|
short effectId = effect.mId;
|
||||||
if (!target.getClass().isActor())
|
if (!target.getClass().isActor())
|
||||||
{
|
{
|
||||||
if (effectId == ESM::MagicEffect::Lock)
|
if (effectId == ESM::MagicEffect::Lock)
|
||||||
|
@ -223,6 +245,28 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute)
|
||||||
|
{
|
||||||
|
int attribute = effect.mArg;
|
||||||
|
AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute);
|
||||||
|
if (effectId == ESM::MagicEffect::DamageAttribute)
|
||||||
|
value.damage(magnitude);
|
||||||
|
else
|
||||||
|
value.restore(magnitude);
|
||||||
|
target.getClass().getCreatureStats(target).setAttribute(attribute, value);
|
||||||
|
}
|
||||||
|
else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill)
|
||||||
|
{
|
||||||
|
if (target.getTypeName() != typeid(ESM::NPC).name())
|
||||||
|
return;
|
||||||
|
int skill = effect.mArg;
|
||||||
|
SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill);
|
||||||
|
if (effectId == ESM::MagicEffect::DamageSkill)
|
||||||
|
value.damage(magnitude);
|
||||||
|
else
|
||||||
|
value.restore(magnitude);
|
||||||
|
}
|
||||||
|
|
||||||
if (effectId == ESM::MagicEffect::CurePoison)
|
if (effectId == ESM::MagicEffect::CurePoison)
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
||||||
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
||||||
|
@ -234,27 +278,45 @@ namespace MWMechanics
|
||||||
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
|
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
||||||
else if (effectId == ESM::MagicEffect::Dispel)
|
else if (effectId == ESM::MagicEffect::Dispel)
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll();
|
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
|
||||||
else if (effectId == ESM::MagicEffect::RemoveCurse)
|
else if (effectId == ESM::MagicEffect::RemoveCurse)
|
||||||
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
|
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
|
||||||
|
|
||||||
else if (effectId == ESM::MagicEffect::DivineIntervention)
|
if (target.getRefData().getHandle() != "player")
|
||||||
|
return;
|
||||||
|
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Ogre::Vector3 worldPos;
|
||||||
|
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(target.getCell(), worldPos))
|
||||||
|
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
|
||||||
|
|
||||||
|
if (effectId == ESM::MagicEffect::DivineIntervention)
|
||||||
{
|
{
|
||||||
// We need to be able to get the world location of an interior cell before implementing this
|
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
|
||||||
// or alternatively, the last known exterior location of the player, which is how vanilla does it.
|
|
||||||
}
|
}
|
||||||
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
||||||
{
|
{
|
||||||
// Same as above
|
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (effectId == ESM::MagicEffect::Mark)
|
else if (effectId == ESM::MagicEffect::Mark)
|
||||||
{
|
{
|
||||||
// TODO
|
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||||
|
target.getCell(), target.getRefData().getPosition());
|
||||||
}
|
}
|
||||||
else if (effectId == ESM::MagicEffect::Recall)
|
else if (effectId == ESM::MagicEffect::Recall)
|
||||||
{
|
{
|
||||||
// TODO
|
MWWorld::CellStore* markedCell = NULL;
|
||||||
|
ESM::Position markedPosition;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().getMarkedPosition(markedCell, markedPosition);
|
||||||
|
if (markedCell)
|
||||||
|
{
|
||||||
|
MWWorld::ActionTeleport action(markedCell->isExterior() ? "" : markedCell->mCell->mName,
|
||||||
|
markedPosition);
|
||||||
|
action.execute(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,6 +440,7 @@ namespace MWMechanics
|
||||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
if (!fail && roll >= successChance)
|
if (!fail && roll >= successChance)
|
||||||
{
|
{
|
||||||
|
if (mCaster.getRefData().getHandle() == "player")
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,7 @@ namespace MWMechanics
|
||||||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||||
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
||||||
|
|
||||||
void applyInstantEffect (const MWWorld::Ptr& target, short effectId, float magnitude);
|
void applyInstantEffect (const MWWorld::Ptr& target, MWMechanics::EffectKey effect, float magnitude);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,14 @@ namespace MWMechanics
|
||||||
random.resize(spell->mEffects.mList.size());
|
random.resize(spell->mEffects.mList.size());
|
||||||
for (unsigned int i=0; i<random.size();++i)
|
for (unsigned int i=0; i<random.size();++i)
|
||||||
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
||||||
mSpells.insert (std::make_pair (spellId, random));
|
mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spells::remove (const std::string& spellId)
|
void Spells::remove (const std::string& spellId)
|
||||||
{
|
{
|
||||||
TContainer::iterator iter = mSpells.find (spellId);
|
std::string lower = Misc::StringUtils::lowerCase(spellId);
|
||||||
|
TContainer::iterator iter = mSpells.find (lower);
|
||||||
|
|
||||||
if (iter!=mSpells.end())
|
if (iter!=mSpells.end())
|
||||||
mSpells.erase (iter);
|
mSpells.erase (iter);
|
||||||
|
@ -192,7 +193,7 @@ namespace MWMechanics
|
||||||
effectIt != list.mList.end(); ++effectIt, ++i)
|
effectIt != list.mList.end(); ++effectIt, ++i)
|
||||||
{
|
{
|
||||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i];
|
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i];
|
||||||
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, magnitude);
|
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,46 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
return !(left==right);
|
return !(left==right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AttributeValue
|
||||||
|
{
|
||||||
|
int mBase;
|
||||||
|
int mModifier;
|
||||||
|
int mDamage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AttributeValue() : mBase(0), mModifier(0), mDamage(0) {}
|
||||||
|
|
||||||
|
int getModified() const { return std::max(0, mBase - mDamage + mModifier); }
|
||||||
|
int getBase() const { return mBase; }
|
||||||
|
int getModifier() const { return mModifier; }
|
||||||
|
|
||||||
|
void setBase(int base) { mBase = std::max(0, base); }
|
||||||
|
void setModifier(int mod) { mModifier = mod; }
|
||||||
|
|
||||||
|
void damage(int damage) { mDamage += damage; }
|
||||||
|
void restore(int amount) { mDamage -= std::min(mDamage, amount); }
|
||||||
|
int getDamage() const { return mDamage; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkillValue : public AttributeValue
|
||||||
|
{
|
||||||
|
float mProgress;
|
||||||
|
public:
|
||||||
|
float getProgress() const { return mProgress; }
|
||||||
|
void setProgress(float progress) { mProgress = progress; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator== (const AttributeValue& left, const AttributeValue& right)
|
||||||
|
{
|
||||||
|
return left.getBase() == right.getBase()
|
||||||
|
&& left.getModifier() == right.getModifier()
|
||||||
|
&& left.getDamage() == right.getDamage();
|
||||||
|
}
|
||||||
|
inline bool operator!= (const AttributeValue& left, const AttributeValue& right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1224,6 +1224,7 @@ void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
|
||||||
for(;iter != mObjectRoot->mEntities.rend();++iter)
|
for(;iter != mObjectRoot->mEntities.rend();++iter)
|
||||||
{
|
{
|
||||||
Ogre::Node *node = (*iter)->getParentNode();
|
Ogre::Node *node = (*iter)->getParentNode();
|
||||||
|
if ((*iter)->isVisible())
|
||||||
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
|
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,25 +19,27 @@ namespace MWRender
|
||||||
Camera::Camera (Ogre::Camera *camera)
|
Camera::Camera (Ogre::Camera *camera)
|
||||||
: mCamera(camera),
|
: mCamera(camera),
|
||||||
mCameraNode(NULL),
|
mCameraNode(NULL),
|
||||||
|
mAnimation(NULL),
|
||||||
mFirstPersonView(true),
|
mFirstPersonView(true),
|
||||||
mPreviewMode(false),
|
mPreviewMode(false),
|
||||||
mFreeLook(true),
|
mFreeLook(true),
|
||||||
mHeight(128.f),
|
|
||||||
mCameraDistance(300.f),
|
|
||||||
mDistanceAdjusted(false),
|
|
||||||
mAnimation(NULL),
|
|
||||||
mNearest(30.f),
|
mNearest(30.f),
|
||||||
mFurthest(800.f),
|
mFurthest(800.f),
|
||||||
mIsNearest(false),
|
mIsNearest(false),
|
||||||
mIsFurthest(false),
|
mIsFurthest(false),
|
||||||
|
mHeight(128.f),
|
||||||
|
mCameraDistance(300.f),
|
||||||
|
mDistanceAdjusted(false),
|
||||||
mVanityToggleQueued(false),
|
mVanityToggleQueued(false),
|
||||||
mViewModeToggleQueued(false)
|
mViewModeToggleQueued(false)
|
||||||
{
|
{
|
||||||
mVanity.enabled = false;
|
mVanity.enabled = false;
|
||||||
mVanity.allowed = true;
|
mVanity.allowed = true;
|
||||||
|
|
||||||
|
mPreviewCam.pitch = 0.f;
|
||||||
mPreviewCam.yaw = 0.f;
|
mPreviewCam.yaw = 0.f;
|
||||||
mPreviewCam.offset = 400.f;
|
mPreviewCam.offset = 400.f;
|
||||||
|
mMainCam.pitch = 0.f;
|
||||||
mMainCam.yaw = 0.f;
|
mMainCam.yaw = 0.f;
|
||||||
mMainCam.offset = 400.f;
|
mMainCam.offset = 400.f;
|
||||||
}
|
}
|
||||||
|
@ -278,6 +280,11 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Camera::getCameraDistance() const
|
||||||
|
{
|
||||||
|
return mCamera->getPosition().z;
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
||||||
{
|
{
|
||||||
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
||||||
|
|
|
@ -105,6 +105,8 @@ namespace MWRender
|
||||||
/// Restore default camera distance for current mode.
|
/// Restore default camera distance for current mode.
|
||||||
void setCameraDistance();
|
void setCameraDistance();
|
||||||
|
|
||||||
|
float getCameraDistance() const;
|
||||||
|
|
||||||
void setAnimation(NpcAnimation *anim);
|
void setAnimation(NpcAnimation *anim);
|
||||||
|
|
||||||
/// Stores focal and camera world positions in passed arguments
|
/// Stores focal and camera world positions in passed arguments
|
||||||
|
|
|
@ -128,7 +128,7 @@ namespace MWRender
|
||||||
|
|
||||||
|
|
||||||
InventoryPreview::InventoryPreview(MWWorld::Ptr character)
|
InventoryPreview::InventoryPreview(MWWorld::Ptr character)
|
||||||
: CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 65, -180), Ogre::Vector3(0,65,0))
|
: CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 62, -200), Ogre::Vector3(0, 62, 0))
|
||||||
, mSelectionBuffer(NULL)
|
, mSelectionBuffer(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,13 +224,6 @@ void LocalMap::render(const float x, const float y,
|
||||||
// try loading from memory
|
// try loading from memory
|
||||||
tex = TextureManager::getSingleton().getByName(texture);
|
tex = TextureManager::getSingleton().getByName(texture);
|
||||||
if (tex.isNull())
|
if (tex.isNull())
|
||||||
{
|
|
||||||
// try loading from disk
|
|
||||||
//if (boost::filesystem::exists(texture+".jpg"))
|
|
||||||
//{
|
|
||||||
/// \todo
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
{
|
{
|
||||||
// render
|
// render
|
||||||
tex = TextureManager::getSingleton().createManual(
|
tex = TextureManager::getSingleton().createManual(
|
||||||
|
@ -278,11 +271,8 @@ void LocalMap::render(const float x, const float y,
|
||||||
tex2->getBuffer()->unlock();
|
tex2->getBuffer()->unlock();
|
||||||
|
|
||||||
mBuffers[texture] = buffer;
|
mBuffers[texture] = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
// save to cache for next time
|
|
||||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mRenderingManager->enableLights(true);
|
mRenderingManager->enableLights(true);
|
||||||
mLight->setVisible(false);
|
mLight->setVisible(false);
|
||||||
|
|
||||||
|
@ -339,8 +329,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
||||||
|
|
||||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
||||||
|
|
||||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
|
||||||
|
|
||||||
if (!mInterior)
|
if (!mInterior)
|
||||||
{
|
{
|
||||||
x = std::ceil(pos.x / sSize)-1;
|
x = std::ceil(pos.x / sSize)-1;
|
||||||
|
|
|
@ -664,12 +664,13 @@ void NpcAnimation::showCarriedLeft(bool show)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 glowColor = getEnchantmentColor(*iter);
|
Ogre::Vector3 glowColor = getEnchantmentColor(*iter);
|
||||||
std::string mesh = MWWorld::Class::get(*iter).getModel(*iter);
|
std::string mesh = MWWorld::Class::get(*iter).getModel(*iter);
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor);
|
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor))
|
||||||
|
{
|
||||||
if (iter->getTypeName() == typeid(ESM::Light).name())
|
if (iter->getTypeName() == typeid(ESM::Light).name())
|
||||||
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
removeIndividualPart(ESM::PRT_Shield);
|
removeIndividualPart(ESM::PRT_Shield);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,10 +109,13 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
|
||||||
|
|
||||||
mFactory->loadAllFiles();
|
mFactory->loadAllFiles();
|
||||||
|
|
||||||
// Set default mipmap level (NB some APIs ignore this)
|
// Compressed textures with 0 mip maps are bugged in 1.8, so disable mipmap generator in that case
|
||||||
// Mipmap generation is currently disabled because it causes issues on Intel/AMD
|
// ( https://ogre3d.atlassian.net/browse/OGRE-259 )
|
||||||
//TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
|
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
|
||||||
|
TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
|
||||||
|
#else
|
||||||
TextureManager::getSingleton().setDefaultNumMipmaps(0);
|
TextureManager::getSingleton().setDefaultNumMipmaps(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set default texture filtering options
|
// Set default texture filtering options
|
||||||
TextureFilterOptions tfo;
|
TextureFilterOptions tfo;
|
||||||
|
@ -325,7 +328,7 @@ void RenderingManager::update (float duration, bool paused)
|
||||||
|
|
||||||
MWWorld::Ptr player = world->getPlayer().getPlayer();
|
MWWorld::Ptr player = world->getPlayer().getPlayer();
|
||||||
|
|
||||||
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude;
|
||||||
mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f)));
|
mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f)));
|
||||||
setAmbientMode();
|
setAmbientMode();
|
||||||
|
|
||||||
|
@ -590,7 +593,7 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
||||||
mAmbientColor = colour;
|
mAmbientColor = colour;
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::NightEye)).mMagnitude;
|
int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).mMagnitude;
|
||||||
Ogre::ColourValue final = colour;
|
Ogre::ColourValue final = colour;
|
||||||
final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f));
|
final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f));
|
||||||
|
|
||||||
|
@ -1023,4 +1026,9 @@ void RenderingManager::enableTerrain(bool enable)
|
||||||
mTerrain->setVisible(false);
|
mTerrain->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float RenderingManager::getCameraDistance() const
|
||||||
|
{
|
||||||
|
return mCamera->getCameraDistance();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
|
|
||||||
bool vanityRotateCamera(const float *rot);
|
bool vanityRotateCamera(const float *rot);
|
||||||
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
||||||
|
float getCameraDistance() const;
|
||||||
|
|
||||||
void setupPlayer(const MWWorld::Ptr &ptr);
|
void setupPlayer(const MWWorld::Ptr &ptr);
|
||||||
void renderPlayer(const MWWorld::Ptr &ptr);
|
void renderPlayer(const MWWorld::Ptr &ptr);
|
||||||
|
|
|
@ -949,9 +949,25 @@ void VideoState::init(const std::string& resourceName)
|
||||||
this->format_ctx->pb = ioCtx;
|
this->format_ctx->pb = ioCtx;
|
||||||
|
|
||||||
// Open video file
|
// Open video file
|
||||||
/// \todo leak here, ffmpeg or valgrind bug ?
|
///
|
||||||
|
/// format_ctx->pb->buffer must be freed by hand,
|
||||||
|
/// if not, valgrind will show memleak, see:
|
||||||
|
///
|
||||||
|
/// https://trac.ffmpeg.org/ticket/1357
|
||||||
|
///
|
||||||
if(!this->format_ctx || avformat_open_input(&this->format_ctx, resourceName.c_str(), NULL, NULL))
|
if(!this->format_ctx || avformat_open_input(&this->format_ctx, resourceName.c_str(), NULL, NULL))
|
||||||
{
|
{
|
||||||
|
if (this->format_ctx != NULL)
|
||||||
|
{
|
||||||
|
if (this->format_ctx->pb != NULL)
|
||||||
|
{
|
||||||
|
av_free(this->format_ctx->pb->buffer);
|
||||||
|
this->format_ctx->pb->buffer = NULL;
|
||||||
|
|
||||||
|
av_free(this->format_ctx->pb);
|
||||||
|
this->format_ctx->pb = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
// "Note that a user-supplied AVFormatContext will be freed on failure."
|
// "Note that a user-supplied AVFormatContext will be freed on failure."
|
||||||
this->format_ctx = NULL;
|
this->format_ctx = NULL;
|
||||||
av_free(ioCtx);
|
av_free(ioCtx);
|
||||||
|
@ -1009,9 +1025,21 @@ void VideoState::deinit()
|
||||||
|
|
||||||
if(this->format_ctx)
|
if(this->format_ctx)
|
||||||
{
|
{
|
||||||
AVIOContext *ioContext = this->format_ctx->pb;
|
///
|
||||||
|
/// format_ctx->pb->buffer must be freed by hand,
|
||||||
|
/// if not, valgrind will show memleak, see:
|
||||||
|
///
|
||||||
|
/// https://trac.ffmpeg.org/ticket/1357
|
||||||
|
///
|
||||||
|
if (this->format_ctx->pb != NULL)
|
||||||
|
{
|
||||||
|
av_free(this->format_ctx->pb->buffer);
|
||||||
|
this->format_ctx->pb->buffer = NULL;
|
||||||
|
|
||||||
|
av_free(this->format_ctx->pb);
|
||||||
|
this->format_ctx->pb = NULL;;
|
||||||
|
}
|
||||||
avformat_close_input(&this->format_ctx);
|
avformat_close_input(&this->format_ctx);
|
||||||
av_free(ioContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,7 @@ Water::~Water()
|
||||||
|
|
||||||
delete mReflection;
|
delete mReflection;
|
||||||
delete mRefraction;
|
delete mRefraction;
|
||||||
|
delete mSimulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::changeCell(const ESM::Cell* cell)
|
void Water::changeCell(const ESM::Cell* cell)
|
||||||
|
|
|
@ -43,10 +43,13 @@ namespace MWScript
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
if (world->findExteriorPosition(cell, pos)) {
|
world->getPlayer().setTeleported(true);
|
||||||
|
if (world->findExteriorPosition(cell, pos))
|
||||||
|
{
|
||||||
world->changeToExteriorCell(pos);
|
world->changeToExteriorCell(pos);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// Change to interior even if findInteriorPosition()
|
// Change to interior even if findInteriorPosition()
|
||||||
// yields false. In this case position will be zero-point.
|
// yields false. In this case position will be zero-point.
|
||||||
world->findInteriorPosition(cell, pos);
|
world->findInteriorPosition(cell, pos);
|
||||||
|
@ -68,13 +71,14 @@ namespace MWScript
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
ESM::Position pos;
|
ESM::Position pos;
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWBase::Environment::get().getWorld()->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
|
world->getPlayer().setTeleported(true);
|
||||||
|
world->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
|
||||||
pos.pos[2] = 0;
|
pos.pos[2] = 0;
|
||||||
|
|
||||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->changeToExteriorCell (pos);
|
world->changeToExteriorCell (pos);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,6 @@ op 0x200007e-0x2000084: Enable Controls
|
||||||
op 0x2000085-0x200008b: Disable Controls
|
op 0x2000085-0x200008b: Disable Controls
|
||||||
op 0x200008c: Unlock
|
op 0x200008c: Unlock
|
||||||
op 0x200008d: Unlock, explicit reference
|
op 0x200008d: Unlock, explicit reference
|
||||||
op 0x200008e: COE
|
|
||||||
op 0x200008e-0x20000a8: GetSkill
|
op 0x200008e-0x20000a8: GetSkill
|
||||||
op 0x20000a9-0x20000c3: GetSkill, explicit reference
|
op 0x20000a9-0x20000c3: GetSkill, explicit reference
|
||||||
op 0x20000c4-0x20000de: SetSkill
|
op 0x20000c4-0x20000de: SetSkill
|
||||||
|
@ -358,5 +357,17 @@ op 0x2000222: GetLineOfSight
|
||||||
op 0x2000223: GetLineOfSightExplicit
|
op 0x2000223: GetLineOfSightExplicit
|
||||||
op 0x2000224: ToggleAI
|
op 0x2000224: ToggleAI
|
||||||
op 0x2000225: ToggleAIExplicit
|
op 0x2000225: ToggleAIExplicit
|
||||||
|
op 0x2000226: COE
|
||||||
opcodes 0x2000226-0x3ffffff unused
|
op 0x2000227: Cast
|
||||||
|
op 0x2000228: Cast, explicit
|
||||||
|
op 0x2000229: ExplodeSpell
|
||||||
|
op 0x200022a: ExplodeSpell, explicit
|
||||||
|
op 0x200022b: RemoveSpellEffects
|
||||||
|
op 0x200022c: RemoveSpellEffects, explicit
|
||||||
|
op 0x200022d: RemoveEffects
|
||||||
|
op 0x200022e: RemoveEffects, explicit
|
||||||
|
op 0x200022f: Resurrect
|
||||||
|
op 0x2000230: Resurrect, explicit
|
||||||
|
op 0x2000231: GetSpellReadied
|
||||||
|
op 0x2000232: GetSpellReadied, explicit
|
||||||
|
opcodes 0x2000233-0x3ffffff unused
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
@ -464,7 +465,20 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
runtime.push(MWWorld::Class::get(ptr).getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon);
|
runtime.push(ptr.getClass().getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Weapon);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpGetSpellReadied : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
runtime.push(ptr.getClass().getNpcStats (ptr).getDrawState () == MWMechanics::DrawState_Spell);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -700,6 +714,42 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpCast : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string spell = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
std::string targetId = ::Misc::StringUtils::lowerCase(runtime.getStringLiteral (runtime[0].mInteger));
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false);
|
||||||
|
|
||||||
|
MWMechanics::CastSpell cast(ptr, target);
|
||||||
|
cast.cast(spell);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpExplodeSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string spell = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWMechanics::CastSpell cast(ptr, ptr);
|
||||||
|
cast.cast(spell);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
@ -739,6 +789,8 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetWeaponDrawnExplicit, new OpGetWeaponDrawn<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetWeaponDrawnExplicit, new OpGetWeaponDrawn<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellReadied, new OpGetSpellReadied<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellReadiedExplicit, new OpGetSpellReadied<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellEffects, new OpGetSpellEffects<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellEffects, new OpGetSpellEffects<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellEffectsExplicit, new OpGetSpellEffects<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetSpellEffectsExplicit, new OpGetSpellEffects<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetCurrentTime, new OpGetCurrentTime);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetCurrentTime, new OpGetCurrentTime);
|
||||||
|
@ -761,6 +813,10 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
|
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation<true>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation<true>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeCast, new OpCast<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeCastExplicit, new OpCast<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpell, new OpExplodeSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpellExplicit, new OpExplodeSpell<ExplicitRef>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,8 +124,8 @@ namespace MWScript
|
||||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWMechanics::Stat<int> attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
||||||
attribute.setModified (value, 0);
|
attribute.setBase (value - (attribute.getModified() - attribute.getBase()));
|
||||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -146,15 +146,11 @@ namespace MWScript
|
||||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
MWMechanics::Stat<int> attribute = MWWorld::Class::get(ptr)
|
MWMechanics::AttributeValue attribute = MWWorld::Class::get(ptr)
|
||||||
.getCreatureStats(ptr)
|
.getCreatureStats(ptr)
|
||||||
.getAttribute(mIndex);
|
.getAttribute(mIndex);
|
||||||
|
|
||||||
value +=
|
attribute.setBase (std::min(100, attribute.getBase() + value));
|
||||||
attribute.getModified();
|
|
||||||
|
|
||||||
attribute
|
|
||||||
.setModified (value, 0, 100);
|
|
||||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -346,17 +342,13 @@ namespace MWScript
|
||||||
const ESM::Class& class_ =
|
const ESM::Class& class_ =
|
||||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find (ref->mBase->mClass);
|
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find (ref->mBase->mClass);
|
||||||
|
|
||||||
float level = 0;
|
float level = stats.getSkill(mIndex).getBase();
|
||||||
float progress = std::modf (stats.getSkill (mIndex).getBase(), &level);
|
float progress = stats.getSkill(mIndex).getProgress();
|
||||||
|
|
||||||
float modifier = stats.getSkill (mIndex).getModifier();
|
int newLevel = value - (stats.getSkill(mIndex).getModified() - stats.getSkill(mIndex).getBase());
|
||||||
|
|
||||||
int newLevel = static_cast<int> (value-modifier);
|
|
||||||
|
|
||||||
if (newLevel<0)
|
if (newLevel<0)
|
||||||
newLevel = 0;
|
newLevel = 0;
|
||||||
else if (newLevel>100)
|
|
||||||
newLevel = 100;
|
|
||||||
|
|
||||||
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
|
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
|
||||||
* stats.getSkillGain (mIndex, class_, -1, newLevel);
|
* stats.getSkillGain (mIndex, class_, -1, newLevel);
|
||||||
|
@ -364,8 +356,8 @@ namespace MWScript
|
||||||
if (progress>=1)
|
if (progress>=1)
|
||||||
progress = 0.999999999;
|
progress = 0.999999999;
|
||||||
|
|
||||||
stats.getSkill (mIndex).set (newLevel + progress);
|
stats.getSkill (mIndex).setBase (newLevel);
|
||||||
stats.getSkill (mIndex).setModifier (modifier);
|
stats.getSkill (mIndex).setProgress(progress);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -385,11 +377,10 @@ namespace MWScript
|
||||||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
value += MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats(ptr);
|
||||||
getModified();
|
|
||||||
|
|
||||||
MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
stats.getSkill(mIndex).
|
||||||
setModified (value, 0, 100);
|
setBase (std::min(100, stats.getSkill(mIndex).getBase() + value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -468,6 +459,38 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpRemoveSpellEffects : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string spellid = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().removeEffects(spellid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpRemoveEffects : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
Interpreter::Type_Integer effectId = runtime[0].mInteger;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().purgeEffect(effectId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class R>
|
template<class R>
|
||||||
class OpGetSpell : public Interpreter::Opcode0
|
class OpGetSpell : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
|
@ -1081,6 +1104,18 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpResurrect : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
ptr.getClass().getCreatureStats(ptr).resurrect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i)
|
for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i)
|
||||||
|
@ -1144,6 +1179,15 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellExplicit,
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellExplicit,
|
||||||
new OpRemoveSpell<ExplicitRef>);
|
new OpRemoveSpell<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffects, new OpRemoveSpellEffects<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffectsExplicit,
|
||||||
|
new OpRemoveSpellEffects<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeResurrect, new OpResurrect<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeResurrectExplicit,
|
||||||
|
new OpResurrect<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffects, new OpRemoveEffects<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffectsExplicit,
|
||||||
|
new OpRemoveEffects<ExplicitRef>);
|
||||||
|
|
||||||
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
||||||
|
|
|
@ -208,6 +208,14 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
}
|
||||||
|
|
||||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float pos = runtime[0].mFloat;
|
Interpreter::Type_Float pos = runtime[0].mFloat;
|
||||||
|
@ -272,6 +280,14 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
}
|
||||||
|
|
||||||
Interpreter::Type_Float x = runtime[0].mFloat;
|
Interpreter::Type_Float x = runtime[0].mFloat;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||||
|
@ -329,6 +345,14 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ptr.getRefData().getHandle() == "player")
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
|
||||||
|
}
|
||||||
|
|
||||||
Interpreter::Type_Float x = runtime[0].mFloat;
|
Interpreter::Type_Float x = runtime[0].mFloat;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||||
|
@ -593,6 +617,10 @@ namespace MWScript
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||||
|
@ -612,6 +640,9 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
const MWWorld::Ptr& ptr = R()(runtime);
|
const MWWorld::Ptr& ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||||
|
@ -647,6 +678,9 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
if (!ptr.isInCell())
|
||||||
|
return;
|
||||||
|
|
||||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||||
|
|
|
@ -158,6 +158,16 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek);
|
||||||
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0)
|
||||||
{
|
{
|
||||||
|
if (mFormatCtx->pb != NULL)
|
||||||
|
{
|
||||||
|
if (mFormatCtx->pb->buffer != NULL)
|
||||||
|
{
|
||||||
|
av_free(mFormatCtx->pb->buffer);
|
||||||
|
mFormatCtx->pb->buffer = NULL;
|
||||||
|
}
|
||||||
|
av_free(mFormatCtx->pb);
|
||||||
|
mFormatCtx->pb = NULL;
|
||||||
|
}
|
||||||
avformat_free_context(mFormatCtx);
|
avformat_free_context(mFormatCtx);
|
||||||
mFormatCtx = NULL;
|
mFormatCtx = NULL;
|
||||||
fail("Failed to allocate input stream");
|
fail("Failed to allocate input stream");
|
||||||
|
@ -195,6 +205,14 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
|
if (mFormatCtx->pb->buffer != NULL)
|
||||||
|
{
|
||||||
|
av_free(mFormatCtx->pb->buffer);
|
||||||
|
mFormatCtx->pb->buffer = NULL;
|
||||||
|
}
|
||||||
|
av_free(mFormatCtx->pb);
|
||||||
|
mFormatCtx->pb = NULL;
|
||||||
|
|
||||||
avformat_close_input(&mFormatCtx);
|
avformat_close_input(&mFormatCtx);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -211,9 +229,22 @@ void FFmpeg_Decoder::close()
|
||||||
|
|
||||||
if(mFormatCtx)
|
if(mFormatCtx)
|
||||||
{
|
{
|
||||||
AVIOContext* context = mFormatCtx->pb;
|
if (mFormatCtx->pb != NULL)
|
||||||
|
{
|
||||||
|
// mFormatCtx->pb->buffer must be freed by hand,
|
||||||
|
// if not, valgrind will show memleak, see:
|
||||||
|
//
|
||||||
|
// https://trac.ffmpeg.org/ticket/1357
|
||||||
|
//
|
||||||
|
if (mFormatCtx->pb->buffer != NULL)
|
||||||
|
{
|
||||||
|
av_free(mFormatCtx->pb->buffer);
|
||||||
|
mFormatCtx->pb->buffer = NULL;
|
||||||
|
}
|
||||||
|
av_free(mFormatCtx->pb);
|
||||||
|
mFormatCtx->pb = NULL;
|
||||||
|
}
|
||||||
avformat_close_input(&mFormatCtx);
|
avformat_close_input(&mFormatCtx);
|
||||||
av_free(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataStream.setNull();
|
mDataStream.setNull();
|
||||||
|
|
|
@ -252,7 +252,7 @@ namespace MWSound
|
||||||
float basevol = volumeFromType(Play_TypeVoice);
|
float basevol = volumeFromType(Play_TypeVoice);
|
||||||
std::string filePath = "Sound/"+filename;
|
std::string filePath = "Sound/"+filename;
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
|
|
||||||
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
|
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
|
||||||
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
||||||
|
@ -354,7 +354,7 @@ namespace MWSound
|
||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, volume, min, max);
|
std::string file = lookup(soundId, volume, min, max);
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
|
|
||||||
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset);
|
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset);
|
||||||
if((mode&Play_NoTrack))
|
if((mode&Play_NoTrack))
|
||||||
|
@ -584,7 +584,7 @@ namespace MWSound
|
||||||
if(!ptr.isEmpty())
|
if(!ptr.isEmpty())
|
||||||
{
|
{
|
||||||
const ESM::Position &pos = ptr.getRefData().getPosition();
|
const ESM::Position &pos = ptr.getRefData().getPosition();
|
||||||
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
const Ogre::Vector3 objpos(pos.pos);
|
||||||
snditer->first->setPosition(objpos);
|
snditer->first->setPosition(objpos);
|
||||||
}
|
}
|
||||||
//update fade out
|
//update fade out
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "../mwgui/container.hpp"
|
#include "../mwgui/container.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/disease.hpp"
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
|
|
||||||
|
@ -21,6 +23,8 @@ namespace MWWorld
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
MWMechanics::diseaseContact(actor, getTarget());
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
|
||||||
MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget(), mLoot);
|
MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget(), mLoot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "player.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -14,9 +15,12 @@ namespace MWWorld
|
||||||
|
|
||||||
void ActionTeleport::executeImp (const Ptr& actor)
|
void ActionTeleport::executeImp (const Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
world->getPlayer().setTeleported(true);
|
||||||
|
|
||||||
if (mCellName.empty())
|
if (mCellName.empty())
|
||||||
MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition);
|
world->changeToExteriorCell (mPosition);
|
||||||
else
|
else
|
||||||
MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, mPosition);
|
world->changeToInteriorCell (mCellName, mPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "refdata.hpp"
|
#include "ptr.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -18,13 +18,13 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
std::vector<Ogre::SceneNode*> mHandles;
|
std::vector<Ogre::SceneNode*> mHandles;
|
||||||
|
|
||||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
bool operator() (MWWorld::Ptr ptr)
|
||||||
{
|
{
|
||||||
Ogre::SceneNode* handle = data.getBaseNode();
|
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||||
if (handle)
|
if (handle)
|
||||||
mHandles.push_back (handle);
|
mHandles.push_back (handle);
|
||||||
|
|
||||||
data.setBaseNode(0);
|
ptr.getRefData().setBaseNode(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -129,9 +129,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
|
||||||
|
|
||||||
if (cell.mState==Ptr::CellStore::State_Preloaded)
|
if (cell.mState==Ptr::CellStore::State_Preloaded)
|
||||||
{
|
{
|
||||||
std::string lowerCase = Misc::StringUtils::lowerCase(name);
|
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), name))
|
||||||
|
|
||||||
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
|
|
||||||
{
|
{
|
||||||
cell.load (mStore, mReader);
|
cell.load (mStore, mReader);
|
||||||
}
|
}
|
||||||
|
@ -261,3 +259,15 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
||||||
// giving up
|
// giving up
|
||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWWorld::Cells::getExteriorPtrs(const std::string &name, std::vector<MWWorld::Ptr> &out)
|
||||||
|
{
|
||||||
|
for (std::map<std::pair<int, int>, Ptr::CellStore>::iterator iter = mExteriors.begin();
|
||||||
|
iter!=mExteriors.end(); ++iter)
|
||||||
|
{
|
||||||
|
Ptr ptr = getPtrAndCache (name, iter->second);
|
||||||
|
if (!ptr.isEmpty())
|
||||||
|
out.push_back(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -47,8 +47,15 @@ namespace MWWorld
|
||||||
|
|
||||||
Ptr getPtr (const std::string& name, CellStore& cellStore, bool searchInContainers = false);
|
Ptr getPtr (const std::string& name, CellStore& cellStore, bool searchInContainers = false);
|
||||||
///< \param searchInContainers Only affect loaded cells.
|
///< \param searchInContainers Only affect loaded cells.
|
||||||
|
/// @note name must be lower case
|
||||||
|
|
||||||
|
/// @note name must be lower case
|
||||||
Ptr getPtr (const std::string& name);
|
Ptr getPtr (const std::string& name);
|
||||||
|
|
||||||
|
/// Get all Ptrs referencing \a name in exterior cells
|
||||||
|
/// @note Due to the current implementation of getPtr this only supports one Ptr per cell.
|
||||||
|
/// @note name must be lower case
|
||||||
|
void getExteriorPtrs (const std::string& name, std::vector<MWWorld::Ptr>& out);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (!iter->mData.getCount())
|
if (!iter->mData.getCount())
|
||||||
continue;
|
continue;
|
||||||
if (!functor (iter->mRef, iter->mData))
|
if (!functor (MWWorld::Ptr(&*iter, this)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -290,6 +290,8 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
|
virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; }
|
||||||
|
|
||||||
virtual Ptr
|
virtual Ptr
|
||||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||||
|
|
||||||
|
|
|
@ -607,7 +607,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito
|
||||||
const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i];
|
const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i];
|
||||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom;
|
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom;
|
||||||
magnitude *= params.mMultiplier;
|
magnitude *= params.mMultiplier;
|
||||||
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), magnitude);
|
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), "", magnitude);
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace MWWorld
|
||||||
|
|
||||||
// initialise
|
// initialise
|
||||||
ESM::CellRef& cellRef = mPtr.getCellRef();
|
ESM::CellRef& cellRef = mPtr.getCellRef();
|
||||||
cellRef.mRefID = name;
|
cellRef.mRefID = Misc::StringUtils::lowerCase(name);
|
||||||
cellRef.mRefnum = -1;
|
cellRef.mRefnum = -1;
|
||||||
cellRef.mScale = 1;
|
cellRef.mScale = 1;
|
||||||
cellRef.mFactIndex = 0;
|
cellRef.mFactIndex = 0;
|
||||||
|
|
|
@ -577,10 +577,28 @@ namespace MWWorld
|
||||||
|
|
||||||
float oldHeight = iter->first.getRefData().getPosition().pos[2];
|
float oldHeight = iter->first.getRefData().getPosition().pos[2];
|
||||||
|
|
||||||
|
bool waterCollision = false;
|
||||||
|
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects()
|
||||||
|
.get(ESM::MagicEffect::WaterWalking).mMagnitude
|
||||||
|
&& cell->hasWater()
|
||||||
|
&& !world->isUnderwater(iter->first.getCell(),
|
||||||
|
Ogre::Vector3(iter->first.getRefData().getPosition().pos)))
|
||||||
|
waterCollision = true;
|
||||||
|
|
||||||
|
btStaticPlaneShape planeShape(btVector3(0,0,1), waterlevel);
|
||||||
|
btCollisionObject object;
|
||||||
|
object.setCollisionShape(&planeShape);
|
||||||
|
|
||||||
|
if (waterCollision)
|
||||||
|
mEngine->dynamicsWorld->addCollisionObject(&object);
|
||||||
|
|
||||||
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
||||||
world->isFlying(iter->first),
|
world->isFlying(iter->first),
|
||||||
waterlevel, mEngine);
|
waterlevel, mEngine);
|
||||||
|
|
||||||
|
if (waterCollision)
|
||||||
|
mEngine->dynamicsWorld->removeCollisionObject(&object);
|
||||||
|
|
||||||
float heightDiff = newpos.z - oldHeight;
|
float heightDiff = newpos.z - oldHeight;
|
||||||
|
|
||||||
if (heightDiff < 0)
|
if (heightDiff < 0)
|
||||||
|
|
|
@ -18,8 +18,11 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
Player::Player (const ESM::NPC *player, const MWBase::World& world)
|
Player::Player (const ESM::NPC *player, const MWBase::World& world)
|
||||||
: mCellStore(0),
|
: mCellStore(0),
|
||||||
|
mLastKnownExteriorPosition(0,0,0),
|
||||||
mAutoMove(false),
|
mAutoMove(false),
|
||||||
mForwardBackward (0)
|
mForwardBackward (0),
|
||||||
|
mTeleported(false),
|
||||||
|
mMarkedCell(NULL)
|
||||||
{
|
{
|
||||||
mPlayer.mBase = player;
|
mPlayer.mBase = player;
|
||||||
mPlayer.mRef.mRefID = "player";
|
mPlayer.mRef.mRefID = "player";
|
||||||
|
@ -145,4 +148,27 @@ namespace MWWorld
|
||||||
MWWorld::Ptr ptr = getPlayer();
|
MWWorld::Ptr ptr = getPlayer();
|
||||||
return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState();
|
return MWWorld::Class::get(ptr).getNpcStats(ptr).getDrawState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Player::wasTeleported() const
|
||||||
|
{
|
||||||
|
return mTeleported;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setTeleported(bool teleported)
|
||||||
|
{
|
||||||
|
mTeleported = teleported;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::markPosition(CellStore *markedCell, ESM::Position markedPosition)
|
||||||
|
{
|
||||||
|
mMarkedCell = markedCell;
|
||||||
|
mMarkedPosition = markedPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::getMarkedPosition(CellStore*& markedCell, ESM::Position &markedPosition) const
|
||||||
|
{
|
||||||
|
markedCell = mMarkedCell;
|
||||||
|
if (mMarkedCell)
|
||||||
|
markedPosition = mMarkedPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "../mwmechanics/drawstate.hpp"
|
#include "../mwmechanics/drawstate.hpp"
|
||||||
|
|
||||||
|
#include <OgreVector3.h>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct NPC;
|
struct NPC;
|
||||||
|
@ -28,13 +30,30 @@ namespace MWWorld
|
||||||
MWWorld::CellStore *mCellStore;
|
MWWorld::CellStore *mCellStore;
|
||||||
std::string mSign;
|
std::string mSign;
|
||||||
|
|
||||||
|
Ogre::Vector3 mLastKnownExteriorPosition;
|
||||||
|
|
||||||
|
ESM::Position mMarkedPosition;
|
||||||
|
// If no position was marked, this is NULL
|
||||||
|
CellStore* mMarkedCell;
|
||||||
|
|
||||||
bool mAutoMove;
|
bool mAutoMove;
|
||||||
int mForwardBackward;
|
int mForwardBackward;
|
||||||
|
bool mTeleported;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Player(const ESM::NPC *player, const MWBase::World& world);
|
Player(const ESM::NPC *player, const MWBase::World& world);
|
||||||
|
|
||||||
|
// For mark/recall magic effects
|
||||||
|
void markPosition (CellStore* markedCell, ESM::Position markedPosition);
|
||||||
|
void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const;
|
||||||
|
|
||||||
|
/// Interiors can not always be mapped to a world position. However
|
||||||
|
/// world position is still required for divine / almsivi magic effects
|
||||||
|
/// and the player arrow on the global map.
|
||||||
|
/// TODO: This should be stored in the savegame, too.
|
||||||
|
void setLastKnownExteriorPosition (const Ogre::Vector3& position) { mLastKnownExteriorPosition = position; }
|
||||||
|
Ogre::Vector3 getLastKnownExteriorPosition() const { return mLastKnownExteriorPosition; }
|
||||||
|
|
||||||
void set (const ESM::NPC *player);
|
void set (const ESM::NPC *player);
|
||||||
|
|
||||||
void setCell (MWWorld::CellStore *cellStore);
|
void setCell (MWWorld::CellStore *cellStore);
|
||||||
|
@ -64,6 +83,9 @@ namespace MWWorld
|
||||||
void yaw(float yaw);
|
void yaw(float yaw);
|
||||||
void pitch(float pitch);
|
void pitch(float pitch);
|
||||||
void roll(float roll);
|
void roll(float roll);
|
||||||
|
|
||||||
|
bool wasTeleported() const;
|
||||||
|
void setTeleported(bool teleported);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -195,7 +195,7 @@ void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
}
|
}
|
||||||
|
|
||||||
mNextWeather = weather;
|
mNextWeather = weather;
|
||||||
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600;
|
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600.f;
|
||||||
}
|
}
|
||||||
mFirstUpdate = false;
|
mFirstUpdate = false;
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,8 @@ void WeatherManager::update(float duration)
|
||||||
|
|
||||||
mWeatherUpdateTime -= timePassed;
|
mWeatherUpdateTime -= timePassed;
|
||||||
|
|
||||||
const bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior());
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
|
||||||
if (!exterior)
|
if (!exterior)
|
||||||
{
|
{
|
||||||
mRendering->sunDisable(false);
|
mRendering->sunDisable(false);
|
||||||
|
@ -334,32 +335,7 @@ void WeatherManager::update(float duration)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exterior
|
switchToNextWeather(false);
|
||||||
std::string regionstr = Misc::StringUtils::lowerCase(MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion);
|
|
||||||
|
|
||||||
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
|
||||||
{
|
|
||||||
mCurrentRegion = regionstr;
|
|
||||||
mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600;
|
|
||||||
|
|
||||||
std::string weatherType = "clear";
|
|
||||||
|
|
||||||
if (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
|
|
||||||
weatherType = mRegionOverrides[regionstr];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// get weather probabilities for the current region
|
|
||||||
const ESM::Region *region =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().search (regionstr);
|
|
||||||
|
|
||||||
if (region != 0)
|
|
||||||
{
|
|
||||||
weatherType = nextWeather(region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setWeather(weatherType, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNextWeather != "")
|
if (mNextWeather != "")
|
||||||
{
|
{
|
||||||
|
@ -708,7 +684,43 @@ float WeatherManager::getWindSpeed() const
|
||||||
return mWindSpeed;
|
return mWindSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WeatherManager::isNight() const
|
bool WeatherManager::isDark() const
|
||||||
{
|
{
|
||||||
return (mHour < mSunriseTime || mHour > mNightStart - 1);
|
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|
||||||
|
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior());
|
||||||
|
return exterior && (mHour < mSunriseTime || mHour > mNightStart - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeatherManager::switchToNextWeather(bool instantly)
|
||||||
|
{
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
if (world->isCellExterior() || world->isCellQuasiExterior())
|
||||||
|
{
|
||||||
|
std::string regionstr = Misc::StringUtils::lowerCase(world->getPlayer().getPlayer().getCell()->mCell->mRegion);
|
||||||
|
|
||||||
|
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
|
||||||
|
{
|
||||||
|
mCurrentRegion = regionstr;
|
||||||
|
mWeatherUpdateTime = mHoursBetweenWeatherChanges * 3600;
|
||||||
|
|
||||||
|
std::string weatherType = "clear";
|
||||||
|
|
||||||
|
if (mRegionOverrides.find(regionstr) != mRegionOverrides.end())
|
||||||
|
{
|
||||||
|
weatherType = mRegionOverrides[regionstr];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get weather probabilities for the current region
|
||||||
|
const ESM::Region *region = world->getStore().get<ESM::Region>().search (regionstr);
|
||||||
|
|
||||||
|
if (region != 0)
|
||||||
|
{
|
||||||
|
weatherType = nextWeather(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setWeather(weatherType, instantly);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ namespace MWWorld
|
||||||
* @param ID of the weather setting to shift to
|
* @param ID of the weather setting to shift to
|
||||||
*/
|
*/
|
||||||
void changeWeather(const std::string& region, const unsigned int id);
|
void changeWeather(const std::string& region, const unsigned int id);
|
||||||
|
void switchToNextWeather(bool instantly = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-frame update
|
* Per-frame update
|
||||||
|
@ -152,7 +153,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void modRegion(const std::string ®ionid, const std::vector<char> &chances);
|
void modRegion(const std::string ®ionid, const std::vector<char> &chances);
|
||||||
|
|
||||||
bool isNight() const;
|
/// @see World::isDark
|
||||||
|
bool isDark() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mHour;
|
float mHour;
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "cellfunctors.hpp"
|
#include "cellfunctors.hpp"
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
#include "inventorystore.hpp"
|
#include "inventorystore.hpp"
|
||||||
|
#include "actionteleport.hpp"
|
||||||
|
|
||||||
#include "contentloader.hpp"
|
#include "contentloader.hpp"
|
||||||
#include "esmloader.hpp"
|
#include "esmloader.hpp"
|
||||||
|
@ -498,12 +499,14 @@ namespace MWWorld
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty())
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
|
std::string lowerCaseName = Misc::StringUtils::lowerCase(name);
|
||||||
|
|
||||||
// active cells
|
// active cells
|
||||||
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
||||||
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
||||||
{
|
{
|
||||||
Ptr::CellStore* cellstore = *iter;
|
Ptr::CellStore* cellstore = *iter;
|
||||||
Ptr ptr = mCells.getPtr (name, *cellstore, true);
|
Ptr ptr = mCells.getPtr (lowerCaseName, *cellstore, true);
|
||||||
|
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty())
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -511,7 +514,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (!activeOnly)
|
if (!activeOnly)
|
||||||
{
|
{
|
||||||
Ptr ptr = mCells.getPtr (name);
|
Ptr ptr = mCells.getPtr (lowerCaseName);
|
||||||
|
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty())
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -793,32 +796,9 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Ptr World::getFacedObject()
|
MWWorld::Ptr World::getFacedObject()
|
||||||
{
|
{
|
||||||
std::pair<float, std::string> result;
|
if (mFacedHandle.empty())
|
||||||
|
return MWWorld::Ptr();
|
||||||
if (!mRendering->occlusionQuerySupported())
|
return searchPtrViaHandle(mFacedHandle);
|
||||||
result = mPhysics->getFacedHandle (getMaxActivationDistance ());
|
|
||||||
else
|
|
||||||
result = std::make_pair (mFacedDistance, mFacedHandle);
|
|
||||||
|
|
||||||
if (result.second.empty())
|
|
||||||
return MWWorld::Ptr ();
|
|
||||||
|
|
||||||
MWWorld::Ptr object = searchPtrViaHandle (result.second);
|
|
||||||
if (object.isEmpty())
|
|
||||||
return object;
|
|
||||||
float ActivationDistance;
|
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
|
||||||
ActivationDistance = getObjectActivationDistance ()*50;
|
|
||||||
else if (object.getTypeName ().find("NPC") != std::string::npos)
|
|
||||||
ActivationDistance = getNpcActivationDistance ();
|
|
||||||
else
|
|
||||||
ActivationDistance = getObjectActivationDistance ();
|
|
||||||
|
|
||||||
if (result.first > ActivationDistance)
|
|
||||||
return MWWorld::Ptr ();
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||||
|
@ -931,7 +911,7 @@ namespace MWWorld
|
||||||
ptr.getRefData().setCount(0);
|
ptr.getRefData().setCount(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (haveToMove)
|
if (haveToMove && ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
mRendering->moveObject(ptr, vec);
|
mRendering->moveObject(ptr, vec);
|
||||||
mPhysics->moveObject (ptr);
|
mPhysics->moveObject (ptr);
|
||||||
|
@ -1060,7 +1040,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::adjustPosition(const Ptr &ptr)
|
void World::adjustPosition(const Ptr &ptr)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]);
|
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos);
|
||||||
|
|
||||||
if(!ptr.getRefData().getBaseNode())
|
if(!ptr.getRefData().getBaseNode())
|
||||||
{
|
{
|
||||||
|
@ -1287,7 +1267,7 @@ namespace MWWorld
|
||||||
mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true);
|
mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mWeatherManager->update (duration);
|
updateWeather(duration);
|
||||||
|
|
||||||
mWorldScene->update (duration, paused);
|
mWorldScene->update (duration, paused);
|
||||||
|
|
||||||
|
@ -1297,6 +1277,12 @@ namespace MWWorld
|
||||||
performUpdateSceneQueries ();
|
performUpdateSceneQueries ();
|
||||||
|
|
||||||
updateWindowManager ();
|
updateWindowManager ();
|
||||||
|
|
||||||
|
if (mPlayer->getPlayer().getCell()->isExterior())
|
||||||
|
{
|
||||||
|
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
|
||||||
|
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::updateWindowManager ()
|
void World::updateWindowManager ()
|
||||||
|
@ -1337,6 +1323,14 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::updateFacedHandle ()
|
void World::updateFacedHandle ()
|
||||||
{
|
{
|
||||||
|
float telekinesisRangeBonus =
|
||||||
|
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
|
||||||
|
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
|
||||||
|
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
|
||||||
|
|
||||||
|
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
|
||||||
|
activationDistance += mRendering->getCameraDistance();
|
||||||
|
|
||||||
// send new query
|
// send new query
|
||||||
// figure out which object we want to test against
|
// figure out which object we want to test against
|
||||||
std::vector < std::pair < float, std::string > > results;
|
std::vector < std::pair < float, std::string > > results;
|
||||||
|
@ -1344,13 +1338,13 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
|
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
|
||||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ());
|
results = mPhysics->getFacedHandles(x, y, activationDistance);
|
||||||
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
|
||||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
results = mPhysics->getFacedHandles(getMaxActivationDistance ());
|
results = mPhysics->getFacedHandles(activationDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore the player and other things we're not interested in
|
// ignore the player and other things we're not interested in
|
||||||
|
@ -1433,10 +1427,8 @@ namespace MWWorld
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<World::DoorMarker> World::getDoorMarkers (CellStore* cell)
|
void World::getDoorMarkers (CellStore* cell, std::vector<World::DoorMarker>& out)
|
||||||
{
|
{
|
||||||
std::vector<World::DoorMarker> result;
|
|
||||||
|
|
||||||
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
||||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||||
|
@ -1452,11 +1444,9 @@ namespace MWWorld
|
||||||
|
|
||||||
newMarker.x = pos.pos[0];
|
newMarker.x = pos.pos[0];
|
||||||
newMarker.y = pos.pos[1];
|
newMarker.y = pos.pos[1];
|
||||||
result.push_back(newMarker);
|
out.push_back(newMarker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
void World::getInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y)
|
||||||
|
@ -1579,7 +1569,7 @@ namespace MWWorld
|
||||||
pos.rot[1] = 0;
|
pos.rot[1] = 0;
|
||||||
|
|
||||||
Ogre::Vector3 orig =
|
Ogre::Vector3 orig =
|
||||||
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);
|
Ogre::Vector3(pos.pos);
|
||||||
Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1);
|
Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1);
|
||||||
|
|
||||||
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
||||||
|
@ -1616,7 +1606,8 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Levitate)).mMagnitude > 0)
|
if(stats.getMagicEffects().get(ESM::MagicEffect::Levitate).mMagnitude > 0
|
||||||
|
&& isLevitationEnabled())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO: Check if flying creature
|
// TODO: Check if flying creature
|
||||||
|
@ -1635,7 +1626,7 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0)
|
if(stats.getMagicEffects().get(ESM::MagicEffect::SlowFall).mMagnitude > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1820,9 +1811,9 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
std::vector<std::string> mHandles;
|
std::vector<std::string> mHandles;
|
||||||
|
|
||||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
bool operator() (Ptr ptr)
|
||||||
{
|
{
|
||||||
Ogre::SceneNode* handle = data.getBaseNode();
|
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode();
|
||||||
if (handle)
|
if (handle)
|
||||||
mHandles.push_back(handle->getName());
|
mHandles.push_back(handle->getName());
|
||||||
return true;
|
return true;
|
||||||
|
@ -1931,17 +1922,8 @@ namespace MWWorld
|
||||||
int y = ext->getGridY();
|
int y = ext->getGridY();
|
||||||
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
||||||
|
|
||||||
ESM::Land* land = getStore().get<ESM::Land>().search(x, y);
|
// Note: Z pos will be adjusted by adjustPosition later
|
||||||
if (land) {
|
|
||||||
if (!land->isDataLoaded(ESM::Land::DATA_VHGT)) {
|
|
||||||
land->loadData(ESM::Land::DATA_VHGT);
|
|
||||||
}
|
|
||||||
pos.pos[2] = land->mLandData->mHeights[ESM::Land::LAND_NUM_VERTS / 2 + 1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cerr << "Land data for cell at (" << x << ", " << y << ") not found\n";
|
|
||||||
pos.pos[2] = 0;
|
pos.pos[2] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1985,11 +1967,11 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
InventoryStore &inv = actor.getClass().getInventoryStore(actor);
|
InventoryStore &inv = actor.getClass().getInventoryStore(actor);
|
||||||
|
|
||||||
inv.equip(InventoryStore::Slot_Robe, inv.ContainerStore::add("WerewolfRobe", 1, actor), actor);
|
inv.equip(InventoryStore::Slot_Robe, inv.ContainerStore::add("werewolfrobe", 1, actor), actor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
actor.getClass().getContainerStore(actor).remove("WerewolfRobe", 1, actor);
|
actor.getClass().getContainerStore(actor).remove("werewolfrobe", 1, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(actor.getRefData().getHandle() == "player")
|
if(actor.getRefData().getHandle() == "player")
|
||||||
|
@ -2018,7 +2000,7 @@ namespace MWWorld
|
||||||
const Store<ESM::GameSetting> &gmst = getStore().get<ESM::GameSetting>();
|
const Store<ESM::GameSetting> &gmst = getStore().get<ESM::GameSetting>();
|
||||||
MWMechanics::NpcStats &stats = Class::get(actor).getNpcStats(actor);
|
MWMechanics::NpcStats &stats = Class::get(actor).getNpcStats(actor);
|
||||||
|
|
||||||
stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0);
|
stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::getGodModeState()
|
bool World::getGodModeState()
|
||||||
|
@ -2286,8 +2268,153 @@ namespace MWWorld
|
||||||
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility);
|
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::isNight() const
|
bool World::isDark() const
|
||||||
{
|
{
|
||||||
return mWeatherManager->isNight();
|
return mWeatherManager->isDark();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result)
|
||||||
|
{
|
||||||
|
MWWorld::CellRefList<ESM::Door>& doors = cell->mDoors;
|
||||||
|
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||||
|
|
||||||
|
// Check if any door in the cell leads to an exterior directly
|
||||||
|
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||||
|
if (ref.mRef.mTeleport && ref.mRef.mDestCell.empty())
|
||||||
|
{
|
||||||
|
ESM::Position pos = ref.mRef.mDoorDest;
|
||||||
|
result = Ogre::Vector3(pos.pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No luck :(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||||
|
const std::string& id, Ogre::Vector3 worldPos)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr closestMarker;
|
||||||
|
float closestDistance = FLT_MAX;
|
||||||
|
|
||||||
|
std::vector<MWWorld::Ptr> markers;
|
||||||
|
mCells.getExteriorPtrs(id, markers);
|
||||||
|
|
||||||
|
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
|
||||||
|
{
|
||||||
|
ESM::Position pos = it->getRefData().getPosition();
|
||||||
|
Ogre::Vector3 markerPos = Ogre::Vector3(pos.pos);
|
||||||
|
float distance = worldPos.squaredDistance(markerPos);
|
||||||
|
if (distance < closestDistance)
|
||||||
|
{
|
||||||
|
closestDistance = distance;
|
||||||
|
closestMarker = *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::ActionTeleport action("", closestMarker.getRefData().getPosition());
|
||||||
|
action.execute(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::updateWeather(float duration)
|
||||||
|
{
|
||||||
|
if (mPlayer->wasTeleported())
|
||||||
|
{
|
||||||
|
mPlayer->setTeleported(false);
|
||||||
|
mWeatherManager->switchToNextWeather(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mWeatherManager->update(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AddDetectedReference
|
||||||
|
{
|
||||||
|
AddDetectedReference(std::vector<Ptr>& out, Ptr detector, World::DetectionType type, float squaredDist)
|
||||||
|
: mOut(out), mDetector(detector), mType(type), mSquaredDist(squaredDist)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Ptr>& mOut;
|
||||||
|
Ptr mDetector;
|
||||||
|
float mSquaredDist;
|
||||||
|
World::DetectionType mType;
|
||||||
|
bool operator() (MWWorld::Ptr ptr)
|
||||||
|
{
|
||||||
|
if (Ogre::Vector3(ptr.getRefData().getPosition().pos).squaredDistance(
|
||||||
|
Ogre::Vector3(mDetector.getRefData().getPosition().pos)) >= mSquaredDist)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!ptr.getRefData().isEnabled())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Consider references inside containers as well
|
||||||
|
if (ptr.getClass().isActor() || ptr.getClass().getTypeName() == typeid(ESM::Container).name())
|
||||||
|
{
|
||||||
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||||
|
{
|
||||||
|
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||||
|
{
|
||||||
|
if (needToAdd(*it))
|
||||||
|
{
|
||||||
|
mOut.push_back(ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needToAdd(ptr))
|
||||||
|
mOut.push_back(ptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needToAdd (MWWorld::Ptr ptr)
|
||||||
|
{
|
||||||
|
if (mType == World::Detect_Creature && ptr.getClass().getTypeName() != typeid(ESM::Creature).name())
|
||||||
|
return false;
|
||||||
|
if (mType == World::Detect_Key && !ptr.getClass().isKey(ptr))
|
||||||
|
return false;
|
||||||
|
if (mType == World::Detect_Enchantment && ptr.getClass().getEnchantment(ptr).empty())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void World::listDetectedReferences(const Ptr &ptr, std::vector<Ptr> &out, DetectionType type)
|
||||||
|
{
|
||||||
|
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||||
|
float dist=0;
|
||||||
|
if (type == World::Detect_Creature)
|
||||||
|
dist = effects.get(ESM::MagicEffect::DetectAnimal).mMagnitude;
|
||||||
|
else if (type == World::Detect_Key)
|
||||||
|
dist = effects.get(ESM::MagicEffect::DetectKey).mMagnitude;
|
||||||
|
else if (type == World::Detect_Enchantment)
|
||||||
|
dist = effects.get(ESM::MagicEffect::DetectEnchantment).mMagnitude;
|
||||||
|
|
||||||
|
if (!dist)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dist = feetToGameUnits(dist);
|
||||||
|
|
||||||
|
AddDetectedReference functor (out, ptr, type, dist*dist);
|
||||||
|
|
||||||
|
const Scene::CellStoreCollection& active = mWorldScene->getActiveCells();
|
||||||
|
for (Scene::CellStoreCollection::const_iterator it = active.begin(); it != active.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::CellStore* cellStore = *it;
|
||||||
|
cellStore->forEach(functor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float World::feetToGameUnits(float feet)
|
||||||
|
{
|
||||||
|
// Looks like there is no GMST for this. This factor was determined in experiments
|
||||||
|
// with the Telekinesis effect.
|
||||||
|
return feet * 22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue