mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 14:23:53 +00:00
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
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
CMakeLists.txt.user
|
||||
Makefile
|
||||
makefile
|
||||
build
|
||||
|
@ -22,6 +21,8 @@ Doxygen
|
|||
.project
|
||||
.settings
|
||||
.directory
|
||||
## qt-creator
|
||||
CMakeLists.txt.user*
|
||||
|
||||
## resources
|
||||
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 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 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
|
||||
- cd /usr/src/gtest/build
|
||||
- sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||
|
|
|
@ -99,8 +99,6 @@ set(OENGINE_BULLET
|
|||
${LIBDIR}/openengine/bullet/BtOgreExtras.h
|
||||
${LIBDIR}/openengine/bullet/BtOgreGP.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.hpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||
|
@ -212,7 +210,7 @@ if (HAVE_UNORDERED_MAP)
|
|||
endif ()
|
||||
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)
|
||||
set(BOOST_COMPONENTS system filesystem program_options)
|
||||
|
||||
IF(BOOST_STATIC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
|
|
|
@ -137,8 +137,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||
target_link_libraries(omwlauncher gcov)
|
||||
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)
|
||||
endif(WIN32)
|
||||
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtXml QtXmlPatterns REQUIRED)
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
|
|
|
@ -74,6 +74,7 @@ add_openmw_dir (mwmechanics
|
|||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||
disease
|
||||
)
|
||||
|
||||
add_openmw_dir (mwbase
|
||||
|
@ -82,6 +83,8 @@ add_openmw_dir (mwbase
|
|||
)
|
||||
|
||||
# Main executable
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
IF(OGRE_STATIC)
|
||||
ADD_DEFINITIONS(-DENABLE_PLUGIN_OctreeSceneManager -DENABLE_PLUGIN_ParticleFX -DENABLE_PLUGIN_GL)
|
||||
|
@ -111,6 +114,7 @@ add_definitions(${SOUND_DEFINE})
|
|||
target_link_libraries(openmw
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SHINY_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${SOUND_INPUT_LIBRARY}
|
||||
|
@ -118,7 +122,6 @@ target_link_libraries(openmw
|
|||
${MYGUI_LIBRARIES}
|
||||
${SDL2_LIBRARY}
|
||||
${MYGUI_PLATFORM_LIBRARIES}
|
||||
${SHINY_LIBRARIES}
|
||||
"oics"
|
||||
"sdl4ogre"
|
||||
components
|
||||
|
@ -137,12 +140,6 @@ if (UNIX AND NOT APPLE)
|
|||
target_link_libraries(openmw ${CMAKE_THREAD_LIBS_INIT})
|
||||
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)
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
find_library(IOKIT_FRAMEWORK IOKit)
|
||||
|
|
|
@ -137,8 +137,8 @@ namespace MWBase
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
|
||||
|
||||
/// Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& 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 std::string& value) = 0;
|
||||
virtual void setValue (const std::string& id, int value) = 0;
|
||||
|
@ -236,8 +236,8 @@ namespace MWBase
|
|||
virtual void onFrame (float frameDuration) = 0;
|
||||
|
||||
/// \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::Stat<int> > getPlayerAttributeValues() = 0;
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
|
||||
virtual SkillList getPlayerMinorSkills() = 0;
|
||||
virtual SkillList getPlayerMajorSkills() = 0;
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace MWBase
|
|||
virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0;
|
||||
///< 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
|
||||
|
||||
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 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,44 +291,36 @@ namespace MWClass
|
|||
{
|
||||
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
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair(0, "");
|
||||
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
// 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);
|
||||
if(race->mData.mFlags & ESM::Race::Beast)
|
||||
{
|
||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts;
|
||||
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
{
|
||||
|
||||
// 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);
|
||||
if(race->mData.mFlags & ESM::Race::Beast)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return std::make_pair(0, "#{sNotifyMessage14}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If equipping a shield, check if there's a twohanded weapon conflicting with it
|
||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
|
|
|
@ -235,37 +235,26 @@ namespace MWClass
|
|||
// slots that this item can be equipped in
|
||||
std::pair<std::vector<int>, bool> slots_ = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
|
||||
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair(0, "");
|
||||
|
||||
std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace;
|
||||
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
// 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);
|
||||
if(race->mData.mFlags & ESM::Race::Beast)
|
||||
{
|
||||
std::vector<ESM::PartReference> parts = ptr.get<ESM::Clothing>()->mBase->mParts.mParts;
|
||||
|
||||
// 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);
|
||||
if(race->mData.mFlags & ESM::Race::Beast)
|
||||
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
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)
|
||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||
}
|
||||
}
|
||||
if((*itr).mPart == ESM::PRT_Head)
|
||||
return std::make_pair(0, "#{sNotifyMessage13}");
|
||||
if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot)
|
||||
return std::make_pair(0, "#{sNotifyMessage15}");
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair (1, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,11 @@ namespace MWClass
|
|||
item.get<ESM::Miscellaneous>();
|
||||
|
||||
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
|
||||
|
@ -252,4 +256,11 @@ namespace MWClass
|
|||
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 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/movement.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
#include "../mwmechanics/disease.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
|
@ -179,29 +180,29 @@ namespace
|
|||
|
||||
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
|
||||
{
|
||||
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
|
||||
{
|
||||
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
|
||||
break;
|
||||
}
|
||||
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
|
||||
{
|
||||
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
// is this a minor or major skill?
|
||||
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
|
||||
{
|
||||
majorMultiplier = 1.0f;
|
||||
break;
|
||||
}
|
||||
// is this a minor or major skill?
|
||||
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
|
||||
{
|
||||
majorMultiplier = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// is this skill in the same Specialization as the class?
|
||||
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find(skillIndex);
|
||||
if (skill->mData.mSpecialization == class_->mData.mSpecialization)
|
||||
{
|
||||
specMultiplier = 0.5f;
|
||||
specBonus = 5;
|
||||
specMultiplier = 0.5f;
|
||||
specBonus = 5;
|
||||
}
|
||||
|
||||
npcStats.getSkill(skillIndex).setBase(
|
||||
|
@ -210,7 +211,7 @@ namespace
|
|||
+ 5
|
||||
+ raceBonus
|
||||
+ 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::Luck).getModified() / 10.0f);
|
||||
hitchance *= stats.getFatigueTerm();
|
||||
hitchance += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyAttack)).mMagnitude -
|
||||
mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
||||
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
|
||||
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
hitchance -= otherstats.getEvasion();
|
||||
|
||||
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
||||
|
@ -493,6 +494,11 @@ namespace MWClass
|
|||
if (!MWBase::Environment::get().getWorld()->getGodModeState())
|
||||
weapon.getCellRef().mCharge -= std::min(std::max(1,
|
||||
(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;
|
||||
}
|
||||
|
@ -512,7 +518,8 @@ namespace MWClass
|
|||
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())
|
||||
{
|
||||
healthdmg = true;
|
||||
|
@ -598,6 +605,9 @@ namespace MWClass
|
|||
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
|
||||
}
|
||||
|
||||
if (!attacker.isEmpty())
|
||||
MWMechanics::diseaseContact(ptr, attacker);
|
||||
|
||||
if(damage > 0.0f)
|
||||
{
|
||||
// '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 -= std::min(std::max(1, (int)damagediff),
|
||||
armorref.mCharge);
|
||||
|
||||
// Armor broken? unequip it
|
||||
if (armorref.mCharge == 0)
|
||||
inv.unequipItem(armor, ptr);
|
||||
|
||||
switch(get(armor).getEquipmentSkill(armor))
|
||||
{
|
||||
case ESM::Skill::LightArmor:
|
||||
|
@ -839,10 +854,11 @@ namespace MWClass
|
|||
float moveSpeed;
|
||||
if(normalizedEncumbrance >= 1.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() +
|
||||
mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude);
|
||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = std::max(0.0f, flySpeed);
|
||||
|
@ -853,7 +869,7 @@ namespace MWClass
|
|||
float swimSpeed = walkSpeed;
|
||||
if(Npc::getStance(ptr, Run, false))
|
||||
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()*
|
||||
fSwimRunAthleticsMult->getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
|
@ -887,7 +903,7 @@ namespace MWClass
|
|||
float x = fJumpAcrobaticsBase->getFloat() +
|
||||
std::pow(a / 15.0f, 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;
|
||||
|
||||
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 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 fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||
|
@ -1015,8 +1031,8 @@ namespace MWClass
|
|||
if(!stats.isWerewolf())
|
||||
{
|
||||
weight = getContainerStore(ptr).getWeight();
|
||||
weight -= stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).mMagnitude;
|
||||
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude;
|
||||
if(weight < 0.0f)
|
||||
weight = 0.0f;
|
||||
}
|
||||
|
|
|
@ -388,28 +388,26 @@ namespace MWClass
|
|||
|
||||
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);
|
||||
|
||||
// equip the item in the first free slot
|
||||
for (std::vector<int>::const_iterator slot=slots_.first.begin();
|
||||
slot!=slots_.first.end(); ++slot)
|
||||
if (slots_.first.empty())
|
||||
return std::make_pair (0, "");
|
||||
|
||||
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::BluntTwoWide ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
|
||||
{
|
||||
if(*slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||
{
|
||||
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::BluntTwoWide ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
|
||||
ptr.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
|
||||
{
|
||||
return std::make_pair (2, "");
|
||||
}
|
||||
}
|
||||
return std::make_pair(1, "");
|
||||
return std::make_pair (2, "");
|
||||
}
|
||||
return std::make_pair (0, "");
|
||||
|
||||
return std::make_pair(1, "");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -262,12 +262,9 @@ namespace MWDialogue
|
|||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, true, true);
|
||||
|
||||
if (!infos.empty())
|
||||
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||
if (info)
|
||||
{
|
||||
const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0];
|
||||
|
||||
parseText (info->mResponse);
|
||||
|
||||
std::string title;
|
||||
|
@ -509,7 +506,7 @@ namespace MWDialogue
|
|||
text = "Bribe";
|
||||
}
|
||||
|
||||
executeTopic (text + (success ? " Success" : " Fail"), true);
|
||||
executeTopic (text + (success ? " Success" : " Fail"));
|
||||
}
|
||||
|
||||
int DialogueManager::getTemporaryDispositionChange() const
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace MWDialogue
|
|||
bool compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code);
|
||||
void executeScript (const std::string& script);
|
||||
|
||||
void executeTopic (const std::string& topic, bool randomResponse=false);
|
||||
void executeTopic (const std::string& topic);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
@ -133,7 +134,8 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert
|
|||
if (isCreature)
|
||||
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".
|
||||
return invert ? (info.mData.mDisposition == 0 || actorDisposition < info.mData.mDisposition)
|
||||
: (actorDisposition >= info.mData.mDisposition);
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace MWGui
|
|||
adjustButton(mNextPageButton);
|
||||
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)
|
||||
{
|
||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||
|
@ -54,6 +59,14 @@ namespace MWGui
|
|||
center();
|
||||
}
|
||||
|
||||
void BookWindow::onMouseWheel(MyGUI::Widget *_sender, int _rel)
|
||||
{
|
||||
if (_rel < 0)
|
||||
nextPage();
|
||||
else
|
||||
prevPage();
|
||||
}
|
||||
|
||||
void BookWindow::clearPages()
|
||||
{
|
||||
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
|
||||
|
@ -89,6 +102,7 @@ namespace MWGui
|
|||
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));
|
||||
pageWidget->setNeedMouseFocus(false);
|
||||
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
|
||||
mPages.push_back(pageWidget);
|
||||
++i;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace MWGui
|
|||
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
||||
void onCloseButtonClicked (MyGUI::Widget* sender);
|
||||
void onTakeButtonClicked (MyGUI::Widget* sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
|
||||
void updatePages();
|
||||
void clearPages();
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace MWGui
|
|||
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)
|
||||
{
|
||||
|
@ -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)
|
||||
mReviewDialog->setSkillValue(parSkill, value);
|
||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
{
|
||||
std::map<int, MWMechanics::Stat<int> > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::Stat<int> >::iterator it = attributes.begin();
|
||||
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
|
||||
it != attributes.end(); ++it)
|
||||
{
|
||||
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();
|
||||
for (std::map<int, MWMechanics::Stat<float> >::iterator it = skills.begin();
|
||||
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
|
||||
it != skills.end(); ++it)
|
||||
{
|
||||
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
||||
|
|
|
@ -31,9 +31,9 @@ namespace MWGui
|
|||
//Show a dialog
|
||||
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 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 doRenderUpdate();
|
||||
|
||||
|
|
|
@ -119,8 +119,6 @@ namespace MWGui
|
|||
|
||||
// Set up the log window
|
||||
mHistory->setOverflowToTheLeft(true);
|
||||
mHistory->setEditStatic(true);
|
||||
mHistory->setVisibleVScroll(true);
|
||||
|
||||
// compiler
|
||||
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
|
||||
|
@ -215,7 +213,7 @@ namespace MWGui
|
|||
{
|
||||
std::vector<std::string> matches;
|
||||
listNames();
|
||||
mCommandLine->setCaption(complete( mCommandLine->getCaption(), matches ));
|
||||
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
|
||||
#if 0
|
||||
int i = 0;
|
||||
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(mCurrent == mCommandHistory.end())
|
||||
mEditString = mCommandLine->getCaption();
|
||||
mEditString = mCommandLine->getOnlyText();
|
||||
|
||||
if(mCurrent != mCommandHistory.begin())
|
||||
{
|
||||
|
@ -259,7 +257,7 @@ namespace MWGui
|
|||
|
||||
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
||||
{
|
||||
const std::string &cm = mCommandLine->getCaption();
|
||||
const std::string &cm = mCommandLine->getOnlyText();
|
||||
if(cm.empty()) return;
|
||||
|
||||
// Add the command to the history, and set the current pointer to
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace MWGui
|
|||
, mWorldMouseOver(false)
|
||||
, mEnemyHealthTimer(0)
|
||||
, mIsDrowning(false)
|
||||
, mWeaponSpellTimer(0.f)
|
||||
, mDrowningFlashTheta(0.f)
|
||||
{
|
||||
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.
|
||||
// Vanilla likely uses a hack like this since there's no other way to prevent it from
|
||||
// being shown or taken.
|
||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
||||
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||
continue;
|
||||
|
||||
ItemStack newItem (item, this, item.getRefData().getCount());
|
||||
|
|
|
@ -163,6 +163,14 @@ namespace MWGui
|
|||
MWWorld::Ptr object = item.mBase;
|
||||
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)
|
||||
{
|
||||
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
|
||||
// likely uses a hack like this since there's no other way to prevent it from being
|
||||
// taken.
|
||||
if(item.getCellRef().mRefID == "WerewolfRobe")
|
||||
if(item.getCellRef().mRefID == "werewolfrobe")
|
||||
return MWWorld::Ptr();
|
||||
return item;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace MWGui
|
|||
// increase attributes
|
||||
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]));
|
||||
|
||||
if (attribute.getBase() >= 100)
|
||||
|
|
|
@ -103,27 +103,80 @@ namespace MWGui
|
|||
|
||||
void LocalMapBase::onMarkerFocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
applyFogOfWar ();
|
||||
}
|
||||
|
||||
void LocalMapBase::onMarkerUnfocused (MyGUI::Widget* w1, MyGUI::Widget* w2)
|
||||
{
|
||||
// Workaround to not make the marker visible if it's under fog of war
|
||||
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)
|
||||
{
|
||||
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
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the map textures
|
||||
for (int mx=0; mx<3; ++mx)
|
||||
{
|
||||
for (int my=0; my<3; ++my)
|
||||
|
@ -138,78 +191,57 @@ namespace MWGui
|
|||
box->setImageTexture(image);
|
||||
else
|
||||
box->setImageTexture("black.png");
|
||||
|
||||
|
||||
// door markers
|
||||
|
||||
// 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)
|
||||
cell = MWBase::Environment::get().getWorld ()->getInterior (mPrefix);
|
||||
else
|
||||
cell = MWBase::Environment::get().getWorld ()->getExterior (x+mx-1, y-(my-1));
|
||||
|
||||
std::vector<MWBase::World::DoorMarker> doors = MWBase::Environment::get().getWorld ()->getDoorMarkers (cell);
|
||||
|
||||
for (std::vector<MWBase::World::DoorMarker>::iterator it = doors.begin(); it != doors.end(); ++it)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
// convert world coordinates to normalized cell coordinates
|
||||
MyGUI::IntCoord widgetCoord;
|
||||
float nX,nY;
|
||||
int cellDx, cellDy;
|
||||
if (!interior)
|
||||
{
|
||||
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;
|
||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||
|
||||
MarkerPosition markerPos;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
mInterior = interior;
|
||||
mCurX = x;
|
||||
mCurY = y;
|
||||
mChanged = false;
|
||||
|
||||
// fog of war
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
// Retrieve the door markers we want to show
|
||||
std::vector<MWBase::World::DoorMarker> doors;
|
||||
if (interior)
|
||||
{
|
||||
MWWorld::CellStore* cell = world->getInterior (mPrefix);
|
||||
world->getDoorMarkers(cell, doors);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int dX=-1; dX<2; ++dX)
|
||||
{
|
||||
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)
|
||||
{
|
||||
MWBase::World::DoorMarker marker = *it;
|
||||
|
||||
MarkerPosition markerPos;
|
||||
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
|
||||
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
|
||||
widgetPos.top - 4,
|
||||
8, 8);
|
||||
++counter;
|
||||
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(counter));
|
||||
markerWidget->setImageResource("DoorMarker");
|
||||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", marker.name);
|
||||
markerWidget->eventMouseSetFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerFocused);
|
||||
markerWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &LocalMapBase::onMarkerUnfocused);
|
||||
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
|
||||
markerWidget->setUserString("IsMarker", "true");
|
||||
markerWidget->setUserData(markerPos);
|
||||
}
|
||||
|
||||
updateMarkers();
|
||||
|
||||
applyFogOfWar();
|
||||
|
||||
// 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)
|
||||
{
|
||||
updateMarkers();
|
||||
|
||||
if (x == mLastPositionX && y == mLastPositionY)
|
||||
return;
|
||||
|
||||
|
@ -255,6 +289,88 @@ namespace MWGui
|
|||
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)
|
||||
|
@ -319,7 +435,7 @@ namespace MWGui
|
|||
|
||||
static int _counter=0;
|
||||
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->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
|
@ -385,7 +501,7 @@ namespace MWGui
|
|||
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -396,20 +512,18 @@ namespace MWGui
|
|||
|
||||
void MapWindow::globalMapUpdatePlayer ()
|
||||
{
|
||||
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::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
|
||||
|
||||
float worldX, worldY;
|
||||
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
|
||||
worldX *= mGlobalMapRender->getWidth();
|
||||
worldY *= mGlobalMapRender->getHeight();
|
||||
|
||||
|
||||
// for interiors, we have no choice other than using the last position & direction.
|
||||
/// \todo save this last position in the savegame?
|
||||
// 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::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
|
||||
Ogre::Vector2 dir (orient.yAxis ().x, orient.yAxis().y);
|
||||
|
||||
float worldX, worldY;
|
||||
mGlobalMapRender->worldPosToImageSpace (pos.x, pos.y, worldX, worldY);
|
||||
worldX *= mGlobalMapRender->getWidth();
|
||||
worldY *= mGlobalMapRender->getHeight();
|
||||
|
||||
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(worldX - 16, worldY - 16));
|
||||
|
||||
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
|
||||
|
@ -444,4 +558,19 @@ namespace MWGui
|
|||
"#{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 onMarkerUnfocused(MyGUI::Widget* w1, MyGUI::Widget* w2);
|
||||
|
||||
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
|
||||
|
||||
virtual void notifyPlayerUpdate() {}
|
||||
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;
|
||||
|
||||
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 cellExplored(int x, int y);
|
||||
|
||||
void setGlobalMapPlayerPosition (float worldX, float worldY);
|
||||
|
||||
virtual void open();
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,6 +16,15 @@ namespace MWGui
|
|||
mLastButtonPressed = -1;
|
||||
}
|
||||
|
||||
MessageBoxManager::~MessageBoxManager ()
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it(mMessageBoxes.begin());
|
||||
for (; it != mMessageBoxes.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageBoxManager::onFrame (float frameDuration)
|
||||
{
|
||||
std::vector<MessageBox*>::iterator it;
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
MessageBoxManager ();
|
||||
~MessageBoxManager ();
|
||||
void onFrame (float frameDuration);
|
||||
void createMessageBox (const std::string& message, bool stat = false);
|
||||
void removeStaticMessageBox ();
|
||||
|
|
|
@ -40,6 +40,14 @@ namespace MWGui
|
|||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++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()
|
||||
&& item.mType != ItemStack::Type_Equipped)
|
||||
mItems.push_back(item);
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace MWGui
|
|||
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
|
||||
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
|
||||
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
||||
}
|
||||
|
||||
// Setup skills
|
||||
|
@ -74,7 +74,7 @@ namespace MWGui
|
|||
|
||||
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)));
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ namespace MWGui
|
|||
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));
|
||||
if (attr == mAttributeWidgets.end())
|
||||
|
@ -161,7 +161,7 @@ namespace MWGui
|
|||
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;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
|
||||
|
@ -279,9 +279,9 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
|
|
@ -38,10 +38,10 @@ namespace MWGui
|
|||
void setMagicka(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 setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value);
|
||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value);
|
||||
|
||||
virtual void open();
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace MWGui
|
|||
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||
|
||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||
std::string mName, mRaceId, mBirthSignId;
|
||||
ESM::Class mKlass;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace MWGui
|
|||
{
|
||||
|
||||
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;
|
||||
newEffectSource.mKey = key;
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace MWGui
|
|||
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
|
||||
|
||||
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
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace MWGui
|
|||
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[] =
|
||||
{
|
||||
|
@ -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;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
|
||||
|
@ -358,22 +358,20 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
int progressPercent = stat.getProgress() * 100;
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
||||
assert(skill);
|
||||
|
||||
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
||||
|
||||
const ESM::Attribute* attr =
|
||||
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||
assert(attr);
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
@ -484,7 +482,6 @@ namespace MWGui
|
|||
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* 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)
|
||||
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace MWGui
|
|||
void setPlayerName(const std::string& playerName);
|
||||
|
||||
/// 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 std::string& 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 setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
|
||||
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mSkillView;
|
||||
|
||||
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<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
||||
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))
|
||||
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
|
||||
if(mMerchant.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "containeritemmodel.hpp"
|
||||
#include "tradeitemmodel.hpp"
|
||||
#include "countdialog.hpp"
|
||||
#include "dialogue.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
@ -296,10 +297,10 @@ namespace MWGui
|
|||
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
||||
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 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 f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
|
||||
|
@ -340,6 +341,9 @@ namespace MWGui
|
|||
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";
|
||||
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;
|
||||
|
||||
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 hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace MWGui
|
|||
}
|
||||
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));
|
||||
if (modified > base)
|
||||
mAttributeValueWidget->_setWidgetState("increased");
|
||||
|
@ -528,14 +528,9 @@ namespace MWGui
|
|||
|
||||
if (mBarTextWidget)
|
||||
{
|
||||
if (mValue >= 0 && mMax > 0)
|
||||
{
|
||||
std::stringstream out;
|
||||
out << mValue << "/" << mMax;
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||
}
|
||||
else
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
|
||||
std::stringstream out;
|
||||
out << mValue << "/" << mMax;
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||
}
|
||||
}
|
||||
void MWDynamicStat::setTitle(const std::string& text)
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace MWGui
|
|||
public:
|
||||
MWAttribute();
|
||||
|
||||
typedef MWMechanics::Stat<int> AttributeValue;
|
||||
typedef MWMechanics::AttributeValue AttributeValue;
|
||||
|
||||
void setAttributeId(int attributeId);
|
||||
void setAttributeValue(const AttributeValue& value);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../mwbase/inputmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
#include "journalwindow.hpp"
|
||||
|
@ -174,11 +175,11 @@ namespace MWGui
|
|||
|
||||
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
||||
|
||||
mCursorManager->setEnabled(true);
|
||||
|
||||
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||
SDL_ShowCursor(false);
|
||||
|
||||
mCursorManager->setEnabled(true);
|
||||
|
||||
// hide mygui's pointer
|
||||
MyGUI::PointerManager::getInstance().setVisible(false);
|
||||
}
|
||||
|
@ -248,12 +249,12 @@ namespace MWGui
|
|||
// Setup player stats
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -322,6 +323,7 @@ namespace MWGui
|
|||
delete mSoulgemDialog;
|
||||
delete mCursorManager;
|
||||
delete mRecharge;
|
||||
delete mCompanionWindow;
|
||||
|
||||
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);
|
||||
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
|
||||
/// allow custom skills.
|
||||
|
@ -774,6 +776,13 @@ namespace MWGui
|
|||
mHud->setCellName( cell->mCell->mName );
|
||||
mMap->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();
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues()
|
||||
std::map<int, MWMechanics::SkillValue > WindowManager::getPlayerSkillValues()
|
||||
{
|
||||
return mPlayerSkillValues;
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues()
|
||||
std::map<int, MWMechanics::AttributeValue > WindowManager::getPlayerAttributeValues()
|
||||
{
|
||||
return mPlayerAttributes;
|
||||
}
|
||||
|
|
|
@ -152,8 +152,8 @@ namespace MWGui
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount);
|
||||
|
||||
///< Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& 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 std::string& value);
|
||||
virtual void setValue (const std::string& id, int value);
|
||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
|||
virtual void onFrame (float frameDuration);
|
||||
|
||||
/// \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::Stat<int> > getPlayerAttributeValues();
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues();
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues();
|
||||
virtual SkillList getPlayerMinorSkills();
|
||||
virtual SkillList getPlayerMajorSkills();
|
||||
|
||||
|
@ -346,9 +346,9 @@ namespace MWGui
|
|||
// Various stats about player as needed by window manager
|
||||
std::string mPlayerName;
|
||||
std::string mPlayerRaceId;
|
||||
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
|
||||
std::map<int, MWMechanics::AttributeValue > mPlayerAttributes;
|
||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mPlayerSkillValues;
|
||||
|
||||
MyGUI::Gui *mGui; // Gui
|
||||
std::vector<GuiMode> mGuiModes;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <MyGUI_RenderManager.h>
|
||||
#include <MyGUI_Widget.h>
|
||||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_EditBox.h>
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
|
@ -19,7 +20,6 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwgui/bookwindow.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
using namespace ICS;
|
||||
|
@ -497,6 +497,9 @@ namespace MWInput
|
|||
edit->deleteTextSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (edit && !edit->getEditStatic())
|
||||
{
|
||||
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
|
||||
{
|
||||
std::string text = edit->getTextSelection();
|
||||
|
@ -591,15 +594,6 @@ namespace MWInput
|
|||
mMouseWheel = int(arg.z);
|
||||
|
||||
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)
|
||||
|
@ -676,7 +670,7 @@ namespace MWInput
|
|||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||
|
||||
// Not allowed before the magic window is accessible
|
||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
|
||||
if (!mControlSwitch["playermagic"])
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
|
@ -691,7 +685,7 @@ namespace MWInput
|
|||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||
|
||||
// Not allowed before the inventory window is accessible
|
||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||
if (!mControlSwitch["playerfighting"])
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
|
@ -831,9 +825,11 @@ namespace MWInput
|
|||
|
||||
void InputManager::updateIdleTime(float dt)
|
||||
{
|
||||
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("fVanityDelay")->getFloat();
|
||||
if (mTimeIdle >= 0.f)
|
||||
mTimeIdle += dt;
|
||||
if (mTimeIdle > 30.f) {
|
||||
if (mTimeIdle > vanityDelay) {
|
||||
MWBase::Environment::get().getWorld()->toggleVanityMode(true);
|
||||
mTimeIdle = -1.f;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,8 @@ namespace MWMechanics
|
|||
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;
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -139,6 +140,7 @@ namespace MWMechanics
|
|||
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
params.mEffects = effects;
|
||||
params.mDisplayName = displayName;
|
||||
params.mCasterHandle = casterHandle;
|
||||
|
||||
if (!exists || stack)
|
||||
mSpells.insert (std::make_pair(id, params));
|
||||
|
@ -148,6 +150,12 @@ namespace MWMechanics
|
|||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::removeEffects(const std::string &id)
|
||||
{
|
||||
mSpells.erase(Misc::StringUtils::lowerCase(id));
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const
|
||||
{
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -164,14 +172,22 @@ namespace MWMechanics
|
|||
float magnitude = effectIt->mMagnitude;
|
||||
|
||||
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)
|
||||
|
@ -187,6 +203,6 @@ namespace MWMechanics
|
|||
effectIt++;
|
||||
}
|
||||
}
|
||||
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ namespace MWMechanics
|
|||
MWWorld::TimeStamp mTimeStamp;
|
||||
std::string mDisplayName;
|
||||
|
||||
// TODO: To handle CASTER_LINKED flag (spell is purged when caster dies),
|
||||
// we should probably store a handle to the caster here.
|
||||
// Handle to the caster that that inflicted this spell on us
|
||||
std::string mCasterHandle;
|
||||
};
|
||||
|
||||
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 effects
|
||||
/// \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);
|
||||
|
||||
/// Remove all active effects
|
||||
void purgeAll ();
|
||||
/// Remove all active effects, if roll succeeds (for each effect)
|
||||
void purgeAll (float chance);
|
||||
|
||||
bool isSpellActive (std::string id) const;
|
||||
///< 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
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
// magic effects
|
||||
|
@ -178,7 +278,7 @@ namespace MWMechanics
|
|||
{
|
||||
// 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();
|
||||
health.setCurrent (health.getCurrent() + 0.1 * endurance);
|
||||
|
@ -217,7 +317,7 @@ namespace MWMechanics
|
|||
// attributes
|
||||
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 -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude);
|
||||
|
@ -229,18 +329,45 @@ namespace MWMechanics
|
|||
for(int i = 0;i < 3;++i)
|
||||
{
|
||||
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyHealth+i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainHealth+i)).mMagnitude);
|
||||
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).mMagnitude -
|
||||
effects.get(ESM::MagicEffect::DrainHealth+i).mMagnitude);
|
||||
|
||||
|
||||
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude;
|
||||
float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).mMagnitude;
|
||||
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
||||
|
||||
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
|
||||
int damageEffects[] = {
|
||||
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
|
||||
|
@ -250,7 +377,7 @@ namespace MWMechanics
|
|||
DynamicStat<float> health = creatureStats.getHealth();
|
||||
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)
|
||||
{
|
||||
|
@ -281,30 +408,32 @@ namespace MWMechanics
|
|||
static std::map<int, std::string> boundItemsMap;
|
||||
if (boundItemsMap.empty())
|
||||
{
|
||||
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "battle_axe";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBoots] = "boots";
|
||||
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "cuirass";
|
||||
boundItemsMap[ESM::MagicEffect::BoundDagger] = "dagger";
|
||||
boundItemsMap[ESM::MagicEffect::BoundGloves] = "gauntlet"; // Note: needs both _left and _right variants, see below
|
||||
boundItemsMap[ESM::MagicEffect::BoundHelm] = "helm";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "longbow";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "longsword";
|
||||
boundItemsMap[ESM::MagicEffect::BoundMace] = "mace";
|
||||
boundItemsMap[ESM::MagicEffect::BoundShield] = "shield";
|
||||
boundItemsMap[ESM::MagicEffect::BoundSpear] = "spear";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBattleAxe] = "sMagicBoundBattleAxeID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundBoots] = "sMagicBoundBootsID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundCuirass] = "sMagicBoundCuirassID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundDagger] = "sMagicBoundDaggerID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundGloves] = "sMagicBoundLeftGauntletID"; // Note: needs RightGauntlet variant too (see below)
|
||||
boundItemsMap[ESM::MagicEffect::BoundHelm] = "sMagicBoundHelmID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongbow] = "sMagicBoundLongbowID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundLongsword] = "sMagicBoundLongswordID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundMace] = "sMagicBoundMaceID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundShield] = "sMagicBoundShieldID";
|
||||
boundItemsMap[ESM::MagicEffect::BoundSpear] = "sMagicBoundSpearID";
|
||||
}
|
||||
|
||||
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
|
||||
{
|
||||
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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
adjustBoundItem(item + "_left", magnitude > 0, ptr);
|
||||
adjustBoundItem(item + "_right", magnitude > 0, ptr);
|
||||
adjustBoundItem("sMagicBoundLeftGauntletID", magnitude > 0, ptr);
|
||||
adjustBoundItem("sMagicBoundRightGauntletID", magnitude > 0, ptr);
|
||||
}
|
||||
else
|
||||
adjustBoundItem(item, magnitude > 0, ptr);
|
||||
|
@ -320,32 +449,34 @@ namespace MWMechanics
|
|||
static std::map<int, std::string> summonMap;
|
||||
if (summonMap.empty())
|
||||
{
|
||||
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "ancestor_ghost_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBear] = "BM_bear_black_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonelord] = "bonelord_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonewalker] = "bonewalker_summon";
|
||||
summonMap[ESM::MagicEffect::SummonBonewolf] = "BM_wolf_bone_summon";
|
||||
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "centurion_sphere_summon";
|
||||
summonMap[ESM::MagicEffect::SummonClannfear] = "clannfear_summon";
|
||||
summonMap[ESM::MagicEffect::SummonDaedroth] = "daedroth_summon";
|
||||
summonMap[ESM::MagicEffect::SummonDremora] = "dremora_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFabricant] = "fabricant_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "atronach_flame_summon";
|
||||
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "atronach_frost_summon";
|
||||
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "golden saint_summon";
|
||||
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "bonewalker_greater_summ";
|
||||
summonMap[ESM::MagicEffect::SummonHunger] = "hunger_summon";
|
||||
summonMap[ESM::MagicEffect::SummonScamp] = "scamp_summon";
|
||||
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "skeleton_summon";
|
||||
summonMap[ESM::MagicEffect::SummonStormAtronach] = "atronach_storm_summon";
|
||||
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "winged twilight_summon";
|
||||
summonMap[ESM::MagicEffect::SummonWolf] = "BM_wolf_grey_summon";
|
||||
summonMap[ESM::MagicEffect::SummonAncestralGhost] = "sMagicAncestralGhostID";
|
||||
summonMap[ESM::MagicEffect::SummonBonelord] = "sMagicBonelordID";
|
||||
summonMap[ESM::MagicEffect::SummonBonewalker] = "sMagicLeastBonewalkerID";
|
||||
summonMap[ESM::MagicEffect::SummonCenturionSphere] = "sMagicCenturionSphereID";
|
||||
summonMap[ESM::MagicEffect::SummonClannfear] = "sMagicClannfearID";
|
||||
summonMap[ESM::MagicEffect::SummonDaedroth] = "sMagicDaedrothID";
|
||||
summonMap[ESM::MagicEffect::SummonDremora] = "sMagicDremoraID";
|
||||
summonMap[ESM::MagicEffect::SummonFabricant] = "sMagicFabricantID";
|
||||
summonMap[ESM::MagicEffect::SummonFlameAtronach] = "sMagicFlameAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonFrostAtronach] = "sMagicFrostAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonGoldenSaint] = "sMagicGoldenSaintID";
|
||||
summonMap[ESM::MagicEffect::SummonGreaterBonewalker] = "sMagicGreaterBonewalkerID";
|
||||
summonMap[ESM::MagicEffect::SummonHunger] = "sMagicHungerID";
|
||||
summonMap[ESM::MagicEffect::SummonScamp] = "sMagicScampID";
|
||||
summonMap[ESM::MagicEffect::SummonSkeletalMinion] = "sMagicSkeletalMinionID";
|
||||
summonMap[ESM::MagicEffect::SummonStormAtronach] = "sMagicStormAtronachID";
|
||||
summonMap[ESM::MagicEffect::SummonWingedTwilight] = "sMagicWingedTwilightID";
|
||||
summonMap[ESM::MagicEffect::SummonWolf] = "sMagicCreature01ID";
|
||||
summonMap[ESM::MagicEffect::SummonBear] = "sMagicCreature02ID";
|
||||
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)
|
||||
{
|
||||
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 (magnitude > 0)
|
||||
|
@ -362,15 +493,20 @@ namespace MWMechanics
|
|||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
MWWorld::CellStore* store = ptr.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), it->second, 1);
|
||||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
std::string creatureID =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
|
||||
|
||||
// TODO: Add AI to follow player and fight for him
|
||||
if (!creatureID.empty())
|
||||
{
|
||||
MWWorld::CellStore* store = ptr.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
||||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
|
||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
||||
// TODO: Add AI to follow player and fight for him
|
||||
|
||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos).getRefData().getHandle()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -396,7 +532,7 @@ namespace MWMechanics
|
|||
// skills
|
||||
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 -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, 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
|
||||
*/
|
||||
if (!isPlayer && !MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile())
|
||||
if (!isPlayer)
|
||||
{
|
||||
if (mTorchPtr.isEmpty())
|
||||
{
|
||||
mTorchPtr = inventoryStore.search("torch_infinite_time");
|
||||
}
|
||||
MWWorld::ContainerStoreIterator torch = inventoryStore.end();
|
||||
for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it)
|
||||
{
|
||||
if (it->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
torch = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (MWBase::Environment::get().getWorld()->isNight())
|
||||
{
|
||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name())
|
||||
if (MWBase::Environment::get().getWorld()->isDark())
|
||||
{
|
||||
inventoryStore.unequipItem(*heldIter, ptr);
|
||||
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())
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (heldIter == inventoryStore.end() && !mTorchPtr.isEmpty())
|
||||
else
|
||||
{
|
||||
heldIter = inventoryStore.add(mTorchPtr, ptr);
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, heldIter, ptr);
|
||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
// At day, unequip lights and auto equip shields or other suitable items
|
||||
// (Note: autoEquip will ignore lights)
|
||||
inventoryStore.autoEquip(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
inventoryStore.unequipItem(*heldIter, ptr);
|
||||
inventoryStore.add(*heldIter, ptr);
|
||||
inventoryStore.autoEquip(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
||||
//If holding a light...
|
||||
if(heldIter.getType() == MWWorld::ContainerStore::Type_Light)
|
||||
{
|
||||
|
@ -516,6 +673,16 @@ namespace MWMechanics
|
|||
|
||||
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)
|
||||
{
|
||||
// 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();
|
||||
|
||||
// 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)];
|
||||
|
||||
if(cls.isEssential(iter->first))
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +806,12 @@ namespace MWMechanics
|
|||
iter->second->updateContinuousVfx();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Actors::restoreDynamicStats()
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace MWMechanics
|
|||
PtrControllerMap mActors;
|
||||
|
||||
std::map<std::string, int> mDeathCount;
|
||||
MWWorld::Ptr mTorchPtr;
|
||||
|
||||
void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused);
|
||||
|
||||
|
@ -49,6 +48,7 @@ namespace MWMechanics
|
|||
public:
|
||||
|
||||
Actors();
|
||||
~Actors();
|
||||
|
||||
/// 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)
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace MWMechanics
|
|||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
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);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
|
||||
|
@ -105,6 +107,7 @@ namespace MWMechanics
|
|||
float directionResult = sqrt(directionX * directionX + directionY * directionY);
|
||||
|
||||
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);
|
||||
|
||||
mPathFinder.clearPath();
|
||||
|
|
|
@ -161,6 +161,7 @@ namespace MWMechanics
|
|||
if(distanceBetweenResult <= mMaxDist * mMaxDist)
|
||||
{
|
||||
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);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
mMaxDist = 470;
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
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);
|
||||
movement.mPosition[1] = 1;
|
||||
|
||||
|
|
|
@ -236,6 +236,7 @@ namespace MWMechanics
|
|||
if(mWalking)
|
||||
{
|
||||
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);
|
||||
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/actionequip.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -1063,15 +1061,19 @@ void CharacterController::update(float duration)
|
|||
|
||||
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
||||
|
||||
if(mHitState != CharState_KnockDown)
|
||||
if (!mSkipAnim)
|
||||
{
|
||||
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
|
||||
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true);
|
||||
}
|
||||
else
|
||||
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
||||
if(mHitState != CharState_KnockDown)
|
||||
{
|
||||
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
|
||||
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true);
|
||||
}
|
||||
else
|
||||
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
||||
|
||||
world->queueMovement(mPtr, vec);
|
||||
}
|
||||
|
||||
world->queueMovement(mPtr, vec);
|
||||
movement = vec;
|
||||
}
|
||||
else if(cls.getCreatureStats(mPtr).isDead())
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace MWMechanics
|
|||
- 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) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
|
@ -158,20 +158,20 @@ namespace MWMechanics
|
|||
|
||||
void CreatureStats::setAttribute(int index, int base)
|
||||
{
|
||||
MWMechanics::Stat<int> current = getAttribute(index);
|
||||
AttributeValue current = getAttribute(index);
|
||||
current.setBase(base);
|
||||
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) {
|
||||
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
|
||||
&& index != ESM::Attribute::Personality
|
||||
|
@ -228,8 +228,8 @@ namespace MWMechanics
|
|||
|
||||
void CreatureStats::setMagicEffects(const MagicEffects &effects)
|
||||
{
|
||||
if (effects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude
|
||||
!= mMagicEffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude)
|
||||
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude
|
||||
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude)
|
||||
mRecalcDynamicStats = true;
|
||||
|
||||
mMagicEffects = effects;
|
||||
|
@ -266,8 +266,10 @@ namespace MWMechanics
|
|||
if (mDead)
|
||||
{
|
||||
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)
|
||||
mDead = false;
|
||||
}
|
||||
|
@ -343,7 +345,7 @@ namespace MWMechanics
|
|||
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
evasion *= getFatigueTerm();
|
||||
evasion += mMagicEffects.get(EffectKey(ESM::MagicEffect::Sanctuary)).mMagnitude;
|
||||
evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).mMagnitude;
|
||||
|
||||
return evasion;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace MWMechanics
|
|||
///
|
||||
class CreatureStats
|
||||
{
|
||||
Stat<int> mAttributes[8];
|
||||
AttributeValue mAttributes[8];
|
||||
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
Spells mSpells;
|
||||
|
@ -49,7 +49,7 @@ namespace MWMechanics
|
|||
|
||||
protected:
|
||||
bool mIsWerewolf;
|
||||
Stat<int> mWerewolfAttributes[8];
|
||||
AttributeValue mWerewolfAttributes[8];
|
||||
|
||||
public:
|
||||
CreatureStats();
|
||||
|
@ -65,7 +65,7 @@ namespace MWMechanics
|
|||
bool canUsePower (const std::string& power) const;
|
||||
void usePower (const std::string& power);
|
||||
|
||||
const Stat<int> & getAttribute(int index) const;
|
||||
const AttributeValue & getAttribute(int index) const;
|
||||
|
||||
const DynamicStat<float> & getHealth() const;
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace MWMechanics
|
|||
|
||||
MagicEffects & getMagicEffects();
|
||||
|
||||
void setAttribute(int index, const Stat<int> &value);
|
||||
void setAttribute(int index, const AttributeValue &value);
|
||||
// Shortcut to set only the 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
|
||||
{
|
||||
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
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "spellcasting.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void MechanicsManager::buildPlayer()
|
||||
|
@ -123,6 +125,19 @@ namespace MWMechanics
|
|||
npcStats.getSkill (index).setBase (
|
||||
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...
|
||||
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
||||
+ 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 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 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;
|
||||
}
|
||||
|
||||
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)
|
||||
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]);
|
||||
}
|
||||
|
||||
MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index)
|
||||
MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
||||
{
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
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)
|
||||
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 (static_cast<int> (base)!=level)
|
||||
if (value.getProgress()>=1)
|
||||
{
|
||||
// skill leveled up
|
||||
increaseSkill(skillIndex, class_, false);
|
||||
}
|
||||
else
|
||||
getSkill (skillIndex).setBase (base);
|
||||
}
|
||||
|
||||
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 (level >= 100)
|
||||
if (base >= 100)
|
||||
return;
|
||||
|
||||
if (preserveProgress)
|
||||
base += 1;
|
||||
else
|
||||
base = level+1;
|
||||
base += 1;
|
||||
|
||||
// if this is a major or minor skill of the class, increase level progress
|
||||
bool levelProgress = false;
|
||||
|
@ -260,6 +251,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
|||
}
|
||||
|
||||
getSkill (skillIndex).setBase (base);
|
||||
if (!preserveProgress)
|
||||
getSkill(skillIndex).setProgress(0);
|
||||
}
|
||||
|
||||
int MWMechanics::NpcStats::getLevelProgress () const
|
||||
|
@ -387,7 +380,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// Oh, Bethesda. It's "Intelligence".
|
||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||
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++)
|
||||
|
@ -401,7 +394,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// "Mercantile"! >_<
|
||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||
ESM::Skill::sSkillNames[i]);
|
||||
mWerewolfSkill[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
||||
mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
}
|
||||
mIsWerewolf = set;
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace MWMechanics
|
|||
DrawState_ mDrawState;
|
||||
int mDisposition;
|
||||
unsigned int mMovementFlags;
|
||||
Stat<float> mSkill[27];
|
||||
Stat<float> mWerewolfSkill[27];
|
||||
SkillValue mSkill[27];
|
||||
SkillValue mWerewolfSkill[27];
|
||||
int mBounty;
|
||||
std::set<std::string> mExpelled;
|
||||
std::map<std::string, int> mFactionReputation;
|
||||
|
@ -94,8 +94,8 @@ namespace MWMechanics
|
|||
|
||||
void setMovementFlag (Flag flag, bool state);
|
||||
|
||||
const Stat<float>& getSkill (int index) const;
|
||||
Stat<float>& getSkill (int index);
|
||||
const SkillValue& getSkill (int index) const;
|
||||
SkillValue& getSkill (int index);
|
||||
|
||||
const std::map<std::string, int>& getFactionRanks() const;
|
||||
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)
|
||||
{
|
||||
removeObject(ptr);
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace MWMechanics
|
|||
|
||||
public:
|
||||
Objects();
|
||||
~Objects();
|
||||
|
||||
void addObject (const MWWorld::Ptr& ptr);
|
||||
///< Register an animated object
|
||||
|
|
|
@ -24,21 +24,13 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
|||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||
mTool.get<ESM::Repair>();
|
||||
|
||||
// unstack tool if required
|
||||
player.getClass().getContainerStore(player).unstack(mTool, player);
|
||||
|
||||
// reduce number of uses left
|
||||
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
|
||||
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::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/actionteleport.hpp"
|
||||
|
||||
#include "../mwrender/animation.hpp"
|
||||
|
||||
|
@ -66,6 +68,12 @@ namespace MWMechanics
|
|||
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
||||
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;
|
||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && target.getClass().isActor())
|
||||
{
|
||||
|
@ -131,9 +139,10 @@ namespace MWMechanics
|
|||
{
|
||||
float random = std::rand() / static_cast<float>(RAND_MAX);
|
||||
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;
|
||||
effect.mKey = MWMechanics::EffectKey(*effectIt);
|
||||
|
@ -152,12 +161,23 @@ namespace MWMechanics
|
|||
ActiveSpells::Effect effect_ = effect;
|
||||
effect_.mMagnitude *= -1;
|
||||
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
|
||||
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)
|
||||
{
|
||||
|
@ -196,11 +216,13 @@ namespace MWMechanics
|
|||
inflict(caster, target, reflectedEffects, range, true);
|
||||
|
||||
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 (effectId == ESM::MagicEffect::Lock)
|
||||
|
@ -223,6 +245,28 @@ namespace MWMechanics
|
|||
}
|
||||
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)
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
||||
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
||||
|
@ -234,27 +278,45 @@ namespace MWMechanics
|
|||
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
||||
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)
|
||||
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
|
||||
// or alternatively, the last known exterior location of the player, which is how vanilla does it.
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker", worldPos);
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
|
||||
{
|
||||
// Same as above
|
||||
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker", worldPos);
|
||||
}
|
||||
|
||||
else if (effectId == ESM::MagicEffect::Mark)
|
||||
{
|
||||
// TODO
|
||||
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
|
||||
target.getCell(), target.getRefData().getPosition());
|
||||
}
|
||||
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,7 +440,8 @@ namespace MWMechanics
|
|||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (!fail && roll >= successChance)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||
if (mCaster.getRefData().getHandle() == "player")
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||
fail = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace MWMechanics
|
|||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||
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());
|
||||
for (unsigned int i=0; i<random.size();++i)
|
||||
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)
|
||||
{
|
||||
TContainer::iterator iter = mSpells.find (spellId);
|
||||
std::string lower = Misc::StringUtils::lowerCase(spellId);
|
||||
TContainer::iterator iter = mSpells.find (lower);
|
||||
|
||||
if (iter!=mSpells.end())
|
||||
mSpells.erase (iter);
|
||||
|
@ -192,7 +193,7 @@ namespace MWMechanics
|
|||
effectIt != list.mList.end(); ++effectIt, ++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);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1224,7 +1224,8 @@ void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
|
|||
for(;iter != mObjectRoot->mEntities.rend();++iter)
|
||||
{
|
||||
Ogre::Node *node = (*iter)->getParentNode();
|
||||
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
|
||||
if ((*iter)->isVisible())
|
||||
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,25 +19,27 @@ namespace MWRender
|
|||
Camera::Camera (Ogre::Camera *camera)
|
||||
: mCamera(camera),
|
||||
mCameraNode(NULL),
|
||||
mAnimation(NULL),
|
||||
mFirstPersonView(true),
|
||||
mPreviewMode(false),
|
||||
mFreeLook(true),
|
||||
mHeight(128.f),
|
||||
mCameraDistance(300.f),
|
||||
mDistanceAdjusted(false),
|
||||
mAnimation(NULL),
|
||||
mNearest(30.f),
|
||||
mFurthest(800.f),
|
||||
mIsNearest(false),
|
||||
mIsFurthest(false),
|
||||
mHeight(128.f),
|
||||
mCameraDistance(300.f),
|
||||
mDistanceAdjusted(false),
|
||||
mVanityToggleQueued(false),
|
||||
mViewModeToggleQueued(false)
|
||||
{
|
||||
mVanity.enabled = false;
|
||||
mVanity.allowed = true;
|
||||
|
||||
mPreviewCam.pitch = 0.f;
|
||||
mPreviewCam.yaw = 0.f;
|
||||
mPreviewCam.offset = 400.f;
|
||||
mMainCam.pitch = 0.f;
|
||||
mMainCam.yaw = 0.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)
|
||||
{
|
||||
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
|
||||
|
|
|
@ -105,6 +105,8 @@ namespace MWRender
|
|||
/// Restore default camera distance for current mode.
|
||||
void setCameraDistance();
|
||||
|
||||
float getCameraDistance() const;
|
||||
|
||||
void setAnimation(NpcAnimation *anim);
|
||||
|
||||
/// Stores focal and camera world positions in passed arguments
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace MWRender
|
|||
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -225,64 +225,54 @@ void LocalMap::render(const float x, const float y,
|
|||
tex = TextureManager::getSingleton().getByName(texture);
|
||||
if (tex.isNull())
|
||||
{
|
||||
// try loading from disk
|
||||
//if (boost::filesystem::exists(texture+".jpg"))
|
||||
//{
|
||||
/// \todo
|
||||
//}
|
||||
//else
|
||||
// render
|
||||
tex = TextureManager::getSingleton().createManual(
|
||||
texture,
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
||||
0,
|
||||
PF_R8G8B8,
|
||||
TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||
|
||||
rtt->setAutoUpdated(false);
|
||||
Viewport* vp = rtt->addViewport(mCellCamera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||
vp->setVisibilityMask(RV_Map);
|
||||
vp->setMaterialScheme("local_map");
|
||||
|
||||
rtt->update();
|
||||
|
||||
// create "fog of war" texture
|
||||
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
||||
texture + "_fog",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
||||
0,
|
||||
PF_A8R8G8B8,
|
||||
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||
|
||||
// create a buffer to use for dynamic operations
|
||||
std::vector<uint32> buffer;
|
||||
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
||||
|
||||
// initialize to (0, 0, 0, 1)
|
||||
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
||||
{
|
||||
// render
|
||||
tex = TextureManager::getSingleton().createManual(
|
||||
texture,
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
||||
0,
|
||||
PF_R8G8B8,
|
||||
TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||
|
||||
rtt->setAutoUpdated(false);
|
||||
Viewport* vp = rtt->addViewport(mCellCamera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||
vp->setVisibilityMask(RV_Map);
|
||||
vp->setMaterialScheme("local_map");
|
||||
|
||||
rtt->update();
|
||||
|
||||
// create "fog of war" texture
|
||||
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
||||
texture + "_fog",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
||||
0,
|
||||
PF_A8R8G8B8,
|
||||
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||
|
||||
// create a buffer to use for dynamic operations
|
||||
std::vector<uint32> buffer;
|
||||
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
||||
|
||||
// initialize to (0, 0, 0, 1)
|
||||
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
||||
{
|
||||
buffer[p] = (255 << 24);
|
||||
}
|
||||
|
||||
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||
tex2->getBuffer()->unlock();
|
||||
|
||||
mBuffers[texture] = buffer;
|
||||
|
||||
// save to cache for next time
|
||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
||||
buffer[p] = (255 << 24);
|
||||
}
|
||||
|
||||
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||
tex2->getBuffer()->unlock();
|
||||
|
||||
mBuffers[texture] = buffer;
|
||||
}
|
||||
|
||||
mRenderingManager->enableLights(true);
|
||||
mLight->setVisible(false);
|
||||
|
||||
|
@ -339,8 +329,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
|
|||
|
||||
Vector3 playerdirection = mCameraRotNode->convertWorldToLocalOrientation(orientation).yAxis();
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().y);
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
x = std::ceil(pos.x / sSize)-1;
|
||||
|
|
|
@ -664,11 +664,12 @@ void NpcAnimation::showCarriedLeft(bool show)
|
|||
{
|
||||
Ogre::Vector3 glowColor = getEnchantmentColor(*iter);
|
||||
std::string mesh = MWWorld::Class::get(*iter).getModel(*iter);
|
||||
addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor);
|
||||
|
||||
if (iter->getTypeName() == typeid(ESM::Light).name())
|
||||
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
||||
if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor))
|
||||
{
|
||||
if (iter->getTypeName() == typeid(ESM::Light).name())
|
||||
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
||||
}
|
||||
}
|
||||
else
|
||||
removeIndividualPart(ESM::PRT_Shield);
|
||||
|
|
|
@ -109,10 +109,13 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
|
|||
|
||||
mFactory->loadAllFiles();
|
||||
|
||||
// Set default mipmap level (NB some APIs ignore this)
|
||||
// Mipmap generation is currently disabled because it causes issues on Intel/AMD
|
||||
//TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
|
||||
// Compressed textures with 0 mip maps are bugged in 1.8, so disable mipmap generator in that case
|
||||
// ( https://ogre3d.atlassian.net/browse/OGRE-259 )
|
||||
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(Settings::Manager::getInt("num mipmaps", "General"));
|
||||
#else
|
||||
TextureManager::getSingleton().setDefaultNumMipmaps(0);
|
||||
#endif
|
||||
|
||||
// Set default texture filtering options
|
||||
TextureFilterOptions tfo;
|
||||
|
@ -325,7 +328,7 @@ void RenderingManager::update (float duration, bool paused)
|
|||
|
||||
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)));
|
||||
setAmbientMode();
|
||||
|
||||
|
@ -590,7 +593,7 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
|||
mAmbientColor = colour;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
float RenderingManager::getCameraDistance() const
|
||||
{
|
||||
return mCamera->getCameraDistance();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
bool vanityRotateCamera(const float *rot);
|
||||
void setCameraDistance(float dist, bool adjust = false, bool override = true);
|
||||
float getCameraDistance() const;
|
||||
|
||||
void setupPlayer(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;
|
||||
|
||||
// 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 != 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."
|
||||
this->format_ctx = NULL;
|
||||
av_free(ioCtx);
|
||||
|
@ -1009,9 +1025,21 @@ void VideoState::deinit()
|
|||
|
||||
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);
|
||||
av_free(ioContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ Water::~Water()
|
|||
|
||||
delete mReflection;
|
||||
delete mRefraction;
|
||||
delete mSimulation;
|
||||
}
|
||||
|
||||
void Water::changeCell(const ESM::Cell* cell)
|
||||
|
|
|
@ -43,10 +43,13 @@ namespace MWScript
|
|||
ESM::Position pos;
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
|
||||
if (world->findExteriorPosition(cell, pos)) {
|
||||
world->getPlayer().setTeleported(true);
|
||||
if (world->findExteriorPosition(cell, pos))
|
||||
{
|
||||
world->changeToExteriorCell(pos);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Change to interior even if findInteriorPosition()
|
||||
// yields false. In this case position will be zero-point.
|
||||
world->findInteriorPosition(cell, pos);
|
||||
|
@ -68,13 +71,14 @@ namespace MWScript
|
|||
runtime.pop();
|
||||
|
||||
ESM::Position pos;
|
||||
|
||||
MWBase::Environment::get().getWorld()->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
world->getPlayer().setTeleported(true);
|
||||
world->indexToPosition (x, y, pos.pos[0], pos.pos[1], true);
|
||||
pos.pos[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 0x200008c: Unlock
|
||||
op 0x200008d: Unlock, explicit reference
|
||||
op 0x200008e: COE
|
||||
op 0x200008e-0x20000a8: GetSkill
|
||||
op 0x20000a9-0x20000c3: GetSkill, explicit reference
|
||||
op 0x20000c4-0x20000de: SetSkill
|
||||
|
@ -358,5 +357,17 @@ op 0x2000222: GetLineOfSight
|
|||
op 0x2000223: GetLineOfSightExplicit
|
||||
op 0x2000224: ToggleAI
|
||||
op 0x2000225: ToggleAIExplicit
|
||||
|
||||
opcodes 0x2000226-0x3ffffff unused
|
||||
op 0x2000226: COE
|
||||
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/creaturestats.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
@ -464,7 +465,20 @@ namespace MWScript
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
@ -739,6 +789,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);
|
||||
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::opcodeGetSpellEffectsExplicit, new OpGetSpellEffects<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetCurrentTime, new OpGetCurrentTime);
|
||||
|
@ -761,6 +813,10 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
|
||||
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;
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::Stat<int> attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
||||
attribute.setModified (value, 0);
|
||||
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
||||
attribute.setBase (value - (attribute.getModified() - attribute.getBase()));
|
||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||
}
|
||||
};
|
||||
|
@ -146,15 +146,11 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::Stat<int> attribute = MWWorld::Class::get(ptr)
|
||||
MWMechanics::AttributeValue attribute = MWWorld::Class::get(ptr)
|
||||
.getCreatureStats(ptr)
|
||||
.getAttribute(mIndex);
|
||||
|
||||
value +=
|
||||
attribute.getModified();
|
||||
|
||||
attribute
|
||||
.setModified (value, 0, 100);
|
||||
attribute.setBase (std::min(100, attribute.getBase() + value));
|
||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||
}
|
||||
};
|
||||
|
@ -346,17 +342,13 @@ namespace MWScript
|
|||
const ESM::Class& class_ =
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find (ref->mBase->mClass);
|
||||
|
||||
float level = 0;
|
||||
float progress = std::modf (stats.getSkill (mIndex).getBase(), &level);
|
||||
float level = stats.getSkill(mIndex).getBase();
|
||||
float progress = stats.getSkill(mIndex).getProgress();
|
||||
|
||||
float modifier = stats.getSkill (mIndex).getModifier();
|
||||
|
||||
int newLevel = static_cast<int> (value-modifier);
|
||||
int newLevel = value - (stats.getSkill(mIndex).getModified() - stats.getSkill(mIndex).getBase());
|
||||
|
||||
if (newLevel<0)
|
||||
newLevel = 0;
|
||||
else if (newLevel>100)
|
||||
newLevel = 100;
|
||||
|
||||
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
|
||||
* stats.getSkillGain (mIndex, class_, -1, newLevel);
|
||||
|
@ -364,8 +356,8 @@ namespace MWScript
|
|||
if (progress>=1)
|
||||
progress = 0.999999999;
|
||||
|
||||
stats.getSkill (mIndex).set (newLevel + progress);
|
||||
stats.getSkill (mIndex).setModifier (modifier);
|
||||
stats.getSkill (mIndex).setBase (newLevel);
|
||||
stats.getSkill (mIndex).setProgress(progress);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -385,11 +377,10 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
value += MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
||||
getModified();
|
||||
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats(ptr);
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
||||
setModified (value, 0, 100);
|
||||
stats.getSkill(mIndex).
|
||||
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>
|
||||
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)
|
||||
{
|
||||
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::opcodeRemoveSpellExplicit,
|
||||
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::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
||||
|
|
|
@ -208,6 +208,14 @@ namespace MWScript
|
|||
{
|
||||
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);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float pos = runtime[0].mFloat;
|
||||
|
@ -272,6 +280,14 @@ namespace MWScript
|
|||
{
|
||||
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;
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||
|
@ -329,6 +345,14 @@ namespace MWScript
|
|||
{
|
||||
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;
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float y = runtime[0].mFloat;
|
||||
|
@ -593,6 +617,10 @@ namespace MWScript
|
|||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||
|
@ -612,6 +640,9 @@ namespace MWScript
|
|||
{
|
||||
const MWWorld::Ptr& ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
|
@ -647,6 +678,9 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
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);
|
||||
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);
|
||||
mFormatCtx = NULL;
|
||||
fail("Failed to allocate input stream");
|
||||
|
@ -195,6 +205,14 @@ void FFmpeg_Decoder::open(const std::string &fname)
|
|||
}
|
||||
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);
|
||||
throw;
|
||||
}
|
||||
|
@ -211,9 +229,22 @@ void FFmpeg_Decoder::close()
|
|||
|
||||
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);
|
||||
av_free(context);
|
||||
}
|
||||
|
||||
mDataStream.setNull();
|
||||
|
|
|
@ -252,7 +252,7 @@ namespace MWSound
|
|||
float basevol = volumeFromType(Play_TypeVoice);
|
||||
std::string filePath = "Sound/"+filename;
|
||||
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,
|
||||
20.0f, 12750.0f, Play_Normal|Play_TypeVoice, 0);
|
||||
|
@ -354,7 +354,7 @@ namespace MWSound
|
|||
float min, max;
|
||||
std::string file = lookup(soundId, volume, min, max);
|
||||
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);
|
||||
if((mode&Play_NoTrack))
|
||||
|
@ -584,7 +584,7 @@ namespace MWSound
|
|||
if(!ptr.isEmpty())
|
||||
{
|
||||
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);
|
||||
}
|
||||
//update fade out
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "../mwgui/container.hpp"
|
||||
|
||||
#include "../mwmechanics/disease.hpp"
|
||||
|
||||
#include "class.hpp"
|
||||
#include "containerstore.hpp"
|
||||
|
||||
|
@ -21,6 +23,8 @@ namespace MWWorld
|
|||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||
return;
|
||||
|
||||
MWMechanics::diseaseContact(actor, getTarget());
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
|
||||
MWBase::Environment::get().getWindowManager()->getContainerWindow()->open(getTarget(), mLoot);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -14,9 +15,12 @@ namespace MWWorld
|
|||
|
||||
void ActionTeleport::executeImp (const Ptr& actor)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
world->getPlayer().setTeleported(true);
|
||||
|
||||
if (mCellName.empty())
|
||||
MWBase::Environment::get().getWorld()->changeToExteriorCell (mPosition);
|
||||
world->changeToExteriorCell (mPosition);
|
||||
else
|
||||
MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, mPosition);
|
||||
world->changeToInteriorCell (mCellName, mPosition);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "refdata.hpp"
|
||||
#include "ptr.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -18,13 +18,13 @@ namespace MWWorld
|
|||
{
|
||||
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)
|
||||
mHandles.push_back (handle);
|
||||
|
||||
data.setBaseNode(0);
|
||||
ptr.getRefData().setBaseNode(0);
|
||||
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)
|
||||
{
|
||||
std::string lowerCase = Misc::StringUtils::lowerCase(name);
|
||||
|
||||
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
|
||||
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), name))
|
||||
{
|
||||
cell.load (mStore, mReader);
|
||||
}
|
||||
|
@ -261,3 +259,15 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|||
// giving up
|
||||
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);
|
||||
///< \param searchInContainers Only affect loaded cells.
|
||||
/// @note name must be lower case
|
||||
|
||||
/// @note name must be lower case
|
||||
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())
|
||||
continue;
|
||||
if (!functor (iter->mRef, iter->mData))
|
||||
if (!functor (MWWorld::Ptr(&*iter, this)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -290,6 +290,8 @@ namespace MWWorld
|
|||
|
||||
virtual bool isPersistent (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; }
|
||||
|
||||
virtual Ptr
|
||||
copyToCell(const Ptr &ptr, CellStore &cell) const;
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
// Don't autoEquip lights
|
||||
if (test.getTypeName() == typeid(ESM::Light).name())
|
||||
{
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test);
|
||||
|
@ -607,7 +607,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito
|
|||
const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i];
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom;
|
||||
magnitude *= params.mMultiplier;
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), magnitude);
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), "", magnitude);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace MWWorld
|
|||
|
||||
// initialise
|
||||
ESM::CellRef& cellRef = mPtr.getCellRef();
|
||||
cellRef.mRefID = name;
|
||||
cellRef.mRefID = Misc::StringUtils::lowerCase(name);
|
||||
cellRef.mRefnum = -1;
|
||||
cellRef.mScale = 1;
|
||||
cellRef.mFactIndex = 0;
|
||||
|
|
|
@ -577,10 +577,28 @@ namespace MWWorld
|
|||
|
||||
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,
|
||||
world->isFlying(iter->first),
|
||||
waterlevel, mEngine);
|
||||
|
||||
if (waterCollision)
|
||||
mEngine->dynamicsWorld->removeCollisionObject(&object);
|
||||
|
||||
float heightDiff = newpos.z - oldHeight;
|
||||
|
||||
if (heightDiff < 0)
|
||||
|
|
|
@ -18,8 +18,11 @@ namespace MWWorld
|
|||
{
|
||||
Player::Player (const ESM::NPC *player, const MWBase::World& world)
|
||||
: mCellStore(0),
|
||||
mLastKnownExteriorPosition(0,0,0),
|
||||
mAutoMove(false),
|
||||
mForwardBackward (0)
|
||||
mForwardBackward (0),
|
||||
mTeleported(false),
|
||||
mMarkedCell(NULL)
|
||||
{
|
||||
mPlayer.mBase = player;
|
||||
mPlayer.mRef.mRefID = "player";
|
||||
|
@ -145,4 +148,27 @@ namespace MWWorld
|
|||
MWWorld::Ptr ptr = getPlayer();
|
||||
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 <OgreVector3.h>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct NPC;
|
||||
|
@ -28,13 +30,30 @@ namespace MWWorld
|
|||
MWWorld::CellStore *mCellStore;
|
||||
std::string mSign;
|
||||
|
||||
Ogre::Vector3 mLastKnownExteriorPosition;
|
||||
|
||||
ESM::Position mMarkedPosition;
|
||||
// If no position was marked, this is NULL
|
||||
CellStore* mMarkedCell;
|
||||
|
||||
bool mAutoMove;
|
||||
int mForwardBackward;
|
||||
|
||||
bool mTeleported;
|
||||
public:
|
||||
|
||||
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 setCell (MWWorld::CellStore *cellStore);
|
||||
|
@ -64,6 +83,9 @@ namespace MWWorld
|
|||
void yaw(float yaw);
|
||||
void pitch(float pitch);
|
||||
void roll(float roll);
|
||||
|
||||
bool wasTeleported() const;
|
||||
void setTeleported(bool teleported);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -195,7 +195,7 @@ void WeatherManager::setWeather(const String& weather, bool instant)
|
|||
}
|
||||
|
||||
mNextWeather = weather;
|
||||
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600;
|
||||
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta * 24.f * 3600.f;
|
||||
}
|
||||
mFirstUpdate = false;
|
||||
}
|
||||
|
@ -324,7 +324,8 @@ void WeatherManager::update(float duration)
|
|||
|
||||
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)
|
||||
{
|
||||
mRendering->sunDisable(false);
|
||||
|
@ -334,32 +335,7 @@ void WeatherManager::update(float duration)
|
|||
return;
|
||||
}
|
||||
|
||||
// Exterior
|
||||
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);
|
||||
}
|
||||
switchToNextWeather(false);
|
||||
|
||||
if (mNextWeather != "")
|
||||
{
|
||||
|
@ -708,7 +684,43 @@ float WeatherManager::getWindSpeed() const
|
|||
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
|
||||
*/
|
||||
void changeWeather(const std::string& region, const unsigned int id);
|
||||
void switchToNextWeather(bool instantly = true);
|
||||
|
||||
/**
|
||||
* Per-frame update
|
||||
|
@ -152,7 +153,8 @@ namespace MWWorld
|
|||
|
||||
void modRegion(const std::string ®ionid, const std::vector<char> &chances);
|
||||
|
||||
bool isNight() const;
|
||||
/// @see World::isDark
|
||||
bool isDark() const;
|
||||
|
||||
private:
|
||||
float mHour;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "cellfunctors.hpp"
|
||||
#include "containerstore.hpp"
|
||||
#include "inventorystore.hpp"
|
||||
#include "actionteleport.hpp"
|
||||
|
||||
#include "contentloader.hpp"
|
||||
#include "esmloader.hpp"
|
||||
|
@ -498,12 +499,14 @@ namespace MWWorld
|
|||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
|
||||
std::string lowerCaseName = Misc::StringUtils::lowerCase(name);
|
||||
|
||||
// active cells
|
||||
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
||||
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
||||
{
|
||||
Ptr::CellStore* cellstore = *iter;
|
||||
Ptr ptr = mCells.getPtr (name, *cellstore, true);
|
||||
Ptr ptr = mCells.getPtr (lowerCaseName, *cellstore, true);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
|
@ -511,7 +514,7 @@ namespace MWWorld
|
|||
|
||||
if (!activeOnly)
|
||||
{
|
||||
Ptr ptr = mCells.getPtr (name);
|
||||
Ptr ptr = mCells.getPtr (lowerCaseName);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
|
@ -793,32 +796,9 @@ namespace MWWorld
|
|||
|
||||
MWWorld::Ptr World::getFacedObject()
|
||||
{
|
||||
std::pair<float, std::string> result;
|
||||
|
||||
if (!mRendering->occlusionQuerySupported())
|
||||
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;
|
||||
if (mFacedHandle.empty())
|
||||
return MWWorld::Ptr();
|
||||
return searchPtrViaHandle(mFacedHandle);
|
||||
}
|
||||
|
||||
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||
|
@ -931,7 +911,7 @@ namespace MWWorld
|
|||
ptr.getRefData().setCount(0);
|
||||
}
|
||||
}
|
||||
if (haveToMove)
|
||||
if (haveToMove && ptr.getRefData().getBaseNode())
|
||||
{
|
||||
mRendering->moveObject(ptr, vec);
|
||||
mPhysics->moveObject (ptr);
|
||||
|
@ -1060,7 +1040,7 @@ namespace MWWorld
|
|||
|
||||
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())
|
||||
{
|
||||
|
@ -1287,7 +1267,7 @@ namespace MWWorld
|
|||
mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true);
|
||||
}
|
||||
|
||||
mWeatherManager->update (duration);
|
||||
updateWeather(duration);
|
||||
|
||||
mWorldScene->update (duration, paused);
|
||||
|
||||
|
@ -1297,6 +1277,12 @@ namespace MWWorld
|
|||
performUpdateSceneQueries ();
|
||||
|
||||
updateWindowManager ();
|
||||
|
||||
if (mPlayer->getPlayer().getCell()->isExterior())
|
||||
{
|
||||
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
|
||||
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos));
|
||||
}
|
||||
}
|
||||
|
||||
void World::updateWindowManager ()
|
||||
|
@ -1337,6 +1323,14 @@ namespace MWWorld
|
|||
|
||||
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
|
||||
// figure out which object we want to test against
|
||||
std::vector < std::pair < float, std::string > > results;
|
||||
|
@ -1344,13 +1338,13 @@ namespace MWWorld
|
|||
{
|
||||
float 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())
|
||||
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
|
||||
}
|
||||
else
|
||||
{
|
||||
results = mPhysics->getFacedHandles(getMaxActivationDistance ());
|
||||
results = mPhysics->getFacedHandles(activationDistance);
|
||||
}
|
||||
|
||||
// ignore the player and other things we're not interested in
|
||||
|
@ -1433,10 +1427,8 @@ namespace MWWorld
|
|||
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;
|
||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||
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.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)
|
||||
|
@ -1579,7 +1569,7 @@ namespace MWWorld
|
|||
pos.rot[1] = 0;
|
||||
|
||||
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);
|
||||
|
||||
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
||||
|
@ -1616,7 +1606,8 @@ namespace MWWorld
|
|||
return false;
|
||||
|
||||
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;
|
||||
|
||||
// TODO: Check if flying creature
|
||||
|
@ -1635,7 +1626,7 @@ namespace MWWorld
|
|||
return false;
|
||||
|
||||
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 false;
|
||||
|
@ -1820,9 +1811,9 @@ namespace MWWorld
|
|||
{
|
||||
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)
|
||||
mHandles.push_back(handle->getName());
|
||||
return true;
|
||||
|
@ -1931,17 +1922,8 @@ namespace MWWorld
|
|||
int y = ext->getGridY();
|
||||
indexToPosition(x, y, pos.pos[0], pos.pos[1], true);
|
||||
|
||||
ESM::Land* land = getStore().get<ESM::Land>().search(x, y);
|
||||
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;
|
||||
}
|
||||
// Note: Z pos will be adjusted by adjustPosition later
|
||||
pos.pos[2] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1985,11 +1967,11 @@ namespace MWWorld
|
|||
{
|
||||
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
|
||||
{
|
||||
actor.getClass().getContainerStore(actor).remove("WerewolfRobe", 1, actor);
|
||||
actor.getClass().getContainerStore(actor).remove("werewolfrobe", 1, actor);
|
||||
}
|
||||
|
||||
if(actor.getRefData().getHandle() == "player")
|
||||
|
@ -2018,7 +2000,7 @@ namespace MWWorld
|
|||
const Store<ESM::GameSetting> &gmst = getStore().get<ESM::GameSetting>();
|
||||
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()
|
||||
|
@ -2286,8 +2268,153 @@ namespace MWWorld
|
|||
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