mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-30 02:56:50 +00:00 
			
		
		
		
	Merge remote-tracking branch 'remotes/upstream/master' into QtOgre
Conflicts: apps/opencs/CMakeLists.txt
This commit is contained in:
		
						commit
						313aed078e
					
				
					 38 changed files with 466 additions and 186 deletions
				
			
		|  | @ -60,7 +60,7 @@ endif (ANDROID) | ||||||
| 
 | 
 | ||||||
| # doxygen main page | # doxygen main page | ||||||
| 
 | 
 | ||||||
| configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/docs/mainpage.hpp") | configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp") | ||||||
| 
 | 
 | ||||||
| option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE) | option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE) | ||||||
| option(OGRE_STATIC  "Link static build of Ogre and Ogre Plugins into the binaries" FALSE) | option(OGRE_STATIC  "Link static build of Ogre and Ogre Plugins into the binaries" FALSE) | ||||||
|  | @ -837,3 +837,26 @@ if (APPLE) | ||||||
|         include(CPack) |         include(CPack) | ||||||
| endif (APPLE) | endif (APPLE) | ||||||
| 
 | 
 | ||||||
|  | # Doxygen Target -- simply run 'make doc' or 'make doc_pages' | ||||||
|  | # output directory for 'make doc'       is "${OpenMW_BINARY_DIR}/docs/Doxygen" | ||||||
|  | # output directory for 'make doc_pages' is "${DOXYGEN_PAGES_OUTPUT_DIR}" if defined | ||||||
|  | #                                       or "${OpenMW_BINARY_DIR}/docs/Pages" otherwise | ||||||
|  | find_package(Doxygen) | ||||||
|  | if (DOXYGEN_FOUND) | ||||||
|  |     # determine output directory for doc_pages | ||||||
|  |     if (NOT DEFINED DOXYGEN_PAGES_OUTPUT_DIR) | ||||||
|  |         set(DOXYGEN_PAGES_OUTPUT_DIR "${OpenMW_BINARY_DIR}/docs/Pages") | ||||||
|  |     endif () | ||||||
|  |     configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.cmake ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY) | ||||||
|  |     configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.cmake ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY) | ||||||
|  |     add_custom_target(doc | ||||||
|  |         ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/Doxyfile | ||||||
|  |         WORKING_DIRECTORY ${OpenMW_BINARY_DIR} | ||||||
|  |         COMMENT "Generating Doxygen documentation at ${OpenMW_BINARY_DIR}/docs/Doxygen" | ||||||
|  |         VERBATIM) | ||||||
|  |     add_custom_target(doc_pages | ||||||
|  |         ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/DoxyfilePages | ||||||
|  |         WORKING_DIRECTORY ${OpenMW_BINARY_DIR} | ||||||
|  |         COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM) | ||||||
|  | endif () | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -77,12 +77,12 @@ opencs_units (view/widget | ||||||
| 
 | 
 | ||||||
| opencs_units (view/render | opencs_units (view/render | ||||||
|     scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget |     scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget | ||||||
|     previewwidget terrainstorage |     previewwidget | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| opencs_units_noqt (view/render | opencs_units_noqt (view/render | ||||||
|     navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight |     navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight | ||||||
|     lightingbright object cell textoverlay overlaymask |     lightingbright object cell terrainstorage textoverlay overlaymask | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| opencs_hdrs_noqt (view/render | opencs_hdrs_noqt (view/render | ||||||
|  |  | ||||||
|  | @ -2,7 +2,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "view.hpp" | #include "view.hpp" | ||||||
| 
 | 
 | ||||||
| CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) | CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) | ||||||
|  |  : mUniversalId (id), mParent (NULL) | ||||||
| { | { | ||||||
|     /// \todo  add a button to the title bar that clones this sub view
 |     /// \todo  add a button to the title bar that clones this sub view
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -335,8 +335,11 @@ namespace MWBase | ||||||
|             virtual void fadeScreenOut(const float time) = 0; |             virtual void fadeScreenOut(const float time) = 0; | ||||||
|             /// Fade the screen to a specified percentage of black, over \a time seconds
 |             /// Fade the screen to a specified percentage of black, over \a time seconds
 | ||||||
|             virtual void fadeScreenTo(const int percent, const float time) = 0; |             virtual void fadeScreenTo(const int percent, const float time) = 0; | ||||||
|             /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
 |             /// Darken the screen to a specified percentage
 | ||||||
|             virtual void setScreenFactor (float factor) = 0; |             virtual void setBlindness(const int percent) = 0; | ||||||
|  | 
 | ||||||
|  |             virtual void activateHitOverlay(bool interrupt=true) = 0; | ||||||
|  |             virtual void setWerewolfOverlay(bool set) = 0; | ||||||
| 
 | 
 | ||||||
|             virtual void toggleDebugWindow() = 0; |             virtual void toggleDebugWindow() = 0; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -297,4 +297,9 @@ namespace MWClass | ||||||
| 
 | 
 | ||||||
|         state2.mTime = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime; |         state2.mTime = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     std::string Light::getSound(const MWWorld::Ptr& ptr) const | ||||||
|  |     { | ||||||
|  |       return ptr.get<ESM::Light>()->mBase->mSound; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -82,6 +82,8 @@ namespace MWClass | ||||||
|             virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) |             virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) | ||||||
|                 const; |                 const; | ||||||
|             ///< Write additional state from \a ptr into \a state.
 |             ///< Write additional state from \a ptr into \a state.
 | ||||||
|  | 
 | ||||||
|  |             virtual std::string getSound(const MWWorld::Ptr& ptr) const; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| #include "../mwmechanics/combat.hpp" | #include "../mwmechanics/combat.hpp" | ||||||
| #include "../mwmechanics/autocalcspell.hpp" | #include "../mwmechanics/autocalcspell.hpp" | ||||||
| #include "../mwmechanics/difficultyscaling.hpp" | #include "../mwmechanics/difficultyscaling.hpp" | ||||||
|  | #include "../mwmechanics/character.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../mwworld/ptr.hpp" | #include "../mwworld/ptr.hpp" | ||||||
| #include "../mwworld/actiontalk.hpp" | #include "../mwworld/actiontalk.hpp" | ||||||
|  | @ -775,7 +776,11 @@ namespace MWClass | ||||||
|                 damage = scaleDamage(damage, attacker, ptr); |                 damage = scaleDamage(damage, attacker, ptr); | ||||||
| 
 | 
 | ||||||
|             if(damage > 0.0f) |             if(damage > 0.0f) | ||||||
|  |             { | ||||||
|                 sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); |                 sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); | ||||||
|  |                 if (ptr.getRefData().getHandle() == "player") | ||||||
|  |                     MWBase::Environment::get().getWindowManager()->activateHitOverlay(); | ||||||
|  |             } | ||||||
|             float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; |             float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; | ||||||
|             setActorHealth(ptr, health, attacker); |             setActorHealth(ptr, health, attacker); | ||||||
|         } |         } | ||||||
|  | @ -1216,60 +1221,43 @@ namespace MWClass | ||||||
| 
 | 
 | ||||||
|     std::string Npc::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const |     std::string Npc::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const | ||||||
|     { |     { | ||||||
|         if(name == "left") |         if(name == "left" || name == "right") | ||||||
|         { |         { | ||||||
|             MWBase::World *world = MWBase::Environment::get().getWorld(); |             MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
|             Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); |             Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); | ||||||
|             if(world->isSwimming(ptr)) |             if(world->isSwimming(ptr)) | ||||||
|                 return "Swim Left"; |                 return (name == "left") ? "Swim Left" : "Swim Right"; | ||||||
|             if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) |             if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) | ||||||
|                 return "FootWaterLeft"; |                 return (name == "left") ? "FootWaterLeft" : "FootWaterRight"; | ||||||
|             if(world->isOnGround(ptr)) |             if(world->isOnGround(ptr)) | ||||||
|             { |             { | ||||||
|  |                 if (ptr.getClass().getNpcStats(ptr).isWerewolf() | ||||||
|  |                         && ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run)) | ||||||
|  |                 { | ||||||
|  |                     MWMechanics::WeaponType weaponType = MWMechanics::WeapType_None; | ||||||
|  |                     MWMechanics::getActiveWeapon(ptr.getClass().getCreatureStats(ptr), ptr.getClass().getInventoryStore(ptr), &weaponType); | ||||||
|  |                     if (weaponType == MWMechanics::WeapType_None) | ||||||
|  |                         return ""; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr); |                 MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr); | ||||||
|                 MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); |                 MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); | ||||||
|                 if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) |                 if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) | ||||||
|                     return "FootBareLeft"; |                     return (name == "left") ? "FootBareLeft" : "FootBareRight"; | ||||||
| 
 | 
 | ||||||
|                 switch(boots->getClass().getEquipmentSkill(*boots)) |                 switch(boots->getClass().getEquipmentSkill(*boots)) | ||||||
|                 { |                 { | ||||||
|                     case ESM::Skill::LightArmor: |                     case ESM::Skill::LightArmor: | ||||||
|                         return "FootLightLeft"; |                         return (name == "left") ? "FootLightLeft" : "FootLightRight"; | ||||||
|                     case ESM::Skill::MediumArmor: |                     case ESM::Skill::MediumArmor: | ||||||
|                         return "FootMedLeft"; |                         return (name == "left") ? "FootMedLeft" : "FootMedRight"; | ||||||
|                     case ESM::Skill::HeavyArmor: |                     case ESM::Skill::HeavyArmor: | ||||||
|                         return "FootHeavyLeft"; |                         return (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return ""; |             return ""; | ||||||
|         } |         } | ||||||
|         if(name == "right") |  | ||||||
|         { |  | ||||||
|             MWBase::World *world = MWBase::Environment::get().getWorld(); |  | ||||||
|             Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); |  | ||||||
|             if(world->isSwimming(ptr)) |  | ||||||
|                 return "Swim Right"; |  | ||||||
|             if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) |  | ||||||
|                 return "FootWaterRight"; |  | ||||||
|             if(world->isOnGround(ptr)) |  | ||||||
|             { |  | ||||||
|                 MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr); |  | ||||||
|                 MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); |  | ||||||
|                 if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) |  | ||||||
|                     return "FootBareRight"; |  | ||||||
| 
 | 
 | ||||||
|                 switch(boots->getClass().getEquipmentSkill(*boots)) |  | ||||||
|                 { |  | ||||||
|                     case ESM::Skill::LightArmor: |  | ||||||
|                         return "FootLightRight"; |  | ||||||
|                     case ESM::Skill::MediumArmor: |  | ||||||
|                         return "FootMedRight"; |  | ||||||
|                     case ESM::Skill::HeavyArmor: |  | ||||||
|                         return "FootHeavyRight"; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return ""; |  | ||||||
|         } |  | ||||||
|         if(name == "land") |         if(name == "land") | ||||||
|         { |         { | ||||||
|             MWBase::World *world = MWBase::Environment::get().getWorld(); |             MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
|  |  | ||||||
|  | @ -507,7 +507,7 @@ namespace MWGui | ||||||
|             mScrollBar->setVisible(true); |             mScrollBar->setVisible(true); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits<int>().max()); |         BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits<int>::max()); | ||||||
| 
 | 
 | ||||||
|         for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) |         for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) | ||||||
|             (*it)->write(typesetter, &mKeywordSearch, mTopicLinks); |             (*it)->write(typesetter, &mKeywordSearch, mTopicLinks); | ||||||
|  |  | ||||||
|  | @ -3,43 +3,91 @@ | ||||||
| namespace MWGui | namespace MWGui | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|     ScreenFader::ScreenFader() |     FadeOp::FadeOp(ScreenFader * fader, float time, float targetAlpha) | ||||||
|  |         : mFader(fader), | ||||||
|  |           mRemainingTime(time), | ||||||
|  |           mTargetTime(time), | ||||||
|  |           mTargetAlpha(targetAlpha), | ||||||
|  |           mStartAlpha(0.f), | ||||||
|  |           mRunning(false) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool FadeOp::isRunning() | ||||||
|  |     { | ||||||
|  |         return mRunning; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void FadeOp::start() | ||||||
|  |     { | ||||||
|  |         if (mRunning) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         mRemainingTime = mTargetTime; | ||||||
|  |         mStartAlpha = mFader->getCurrentAlpha(); | ||||||
|  |         mRunning = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void FadeOp::update(float dt) | ||||||
|  |     { | ||||||
|  |         if (!mRunning) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         if (mRemainingTime <= 0 || mStartAlpha == mTargetAlpha) | ||||||
|  |         { | ||||||
|  |             finish(); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         float currentAlpha = mFader->getCurrentAlpha(); | ||||||
|  |         if (mStartAlpha > mTargetAlpha) | ||||||
|  |         { | ||||||
|  |             currentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); | ||||||
|  |             if (currentAlpha < mTargetAlpha) | ||||||
|  |                 currentAlpha = mTargetAlpha; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             currentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); | ||||||
|  |             if (currentAlpha > mTargetAlpha) | ||||||
|  |                 currentAlpha = mTargetAlpha; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         mFader->notifyAlphaChanged(currentAlpha); | ||||||
|  | 
 | ||||||
|  |         mRemainingTime -= dt; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void FadeOp::finish() | ||||||
|  |     { | ||||||
|  |         mRunning = false; | ||||||
|  |         mFader->notifyOperationFinished(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ScreenFader::ScreenFader(const std::string & texturePath) | ||||||
|         : WindowBase("openmw_screen_fader.layout") |         : WindowBase("openmw_screen_fader.layout") | ||||||
|         , mMode(FadingMode_In) |  | ||||||
|         , mRemainingTime(0.f) |  | ||||||
|         , mTargetTime(0.f) |  | ||||||
|         , mTargetAlpha(0.f) |  | ||||||
|         , mCurrentAlpha(0.f) |         , mCurrentAlpha(0.f) | ||||||
|         , mStartAlpha(0.f) |  | ||||||
|         , mFactor(1.f) |         , mFactor(1.f) | ||||||
|  |         , mRepeat(false) | ||||||
|     { |     { | ||||||
|         mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); |         mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); | ||||||
| 
 |         setTexture(texturePath); | ||||||
|         setVisible(false); |         setVisible(false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void ScreenFader::setTexture(const std::string & texturePath) | ||||||
|  |     { | ||||||
|  |         mMainWidget->setProperty("ImageTexture", texturePath); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void ScreenFader::update(float dt) |     void ScreenFader::update(float dt) | ||||||
|     { |     { | ||||||
|         if (mRemainingTime > 0) |         if (!mQueue.empty()) | ||||||
|         { |         { | ||||||
|             if (mMode == FadingMode_In) |             if (!mQueue.front()->isRunning()) | ||||||
|             { |                 mQueue.front()->start(); | ||||||
|                 mCurrentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); |             mQueue.front()->update(dt); | ||||||
|                 if (mCurrentAlpha < mTargetAlpha) mCurrentAlpha = mTargetAlpha; |  | ||||||
|             } |  | ||||||
|             else if (mMode == FadingMode_Out) |  | ||||||
|             { |  | ||||||
|                 mCurrentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); |  | ||||||
|                 if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             mRemainingTime -= dt; |  | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f) |  | ||||||
|             mMainWidget->setVisible(false); |  | ||||||
|         else |  | ||||||
|             applyAlpha(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ScreenFader::applyAlpha() |     void ScreenFader::applyAlpha() | ||||||
|  | @ -50,62 +98,79 @@ namespace MWGui | ||||||
| 
 | 
 | ||||||
|     void ScreenFader::fadeIn(float time) |     void ScreenFader::fadeIn(float time) | ||||||
|     { |     { | ||||||
|         if (time<0.f) return; |         queue(time, 1.f); | ||||||
|         if (time==0.f) |  | ||||||
|         { |  | ||||||
|             mCurrentAlpha = 0.f; |  | ||||||
|             applyAlpha(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         mStartAlpha = mCurrentAlpha; |  | ||||||
|         mTargetAlpha = 0.f; |  | ||||||
|         mMode = FadingMode_In; |  | ||||||
|         mTargetTime = time; |  | ||||||
|         mRemainingTime = time; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ScreenFader::fadeOut(const float time) |     void ScreenFader::fadeOut(const float time) | ||||||
|     { |     { | ||||||
|         if (time<0.f) return; |         queue(time, 0.f); | ||||||
|         if (time==0.f) |  | ||||||
|         { |  | ||||||
|             mCurrentAlpha = 1.f; |  | ||||||
|             applyAlpha(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         mStartAlpha = mCurrentAlpha; |  | ||||||
|         mTargetAlpha = 1.f; |  | ||||||
|         mMode = FadingMode_Out; |  | ||||||
|         mTargetTime = time; |  | ||||||
|         mRemainingTime = time; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ScreenFader::fadeTo(const int percent, const float time) |     void ScreenFader::fadeTo(const int percent, const float time) | ||||||
|     { |     { | ||||||
|         if (time<0.f) return; |         queue(time, percent/100.f); | ||||||
|         if (time==0.f) |  | ||||||
|         { |  | ||||||
|             mCurrentAlpha = percent/100.f; |  | ||||||
|             applyAlpha(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         mStartAlpha = mCurrentAlpha; |  | ||||||
|         mTargetAlpha = percent/100.f; |  | ||||||
| 
 |  | ||||||
|         if (mTargetAlpha == mStartAlpha) return; |  | ||||||
|         else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out; |  | ||||||
|         else mMode = FadingMode_In; |  | ||||||
| 
 |  | ||||||
|         mTargetTime = time; |  | ||||||
|         mRemainingTime = time; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ScreenFader::setFactor(float factor) |     void ScreenFader::setFactor(float factor) | ||||||
|     { |     { | ||||||
|         mFactor = factor; |         mFactor = factor; | ||||||
|  |         applyAlpha(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void ScreenFader::setRepeat(bool repeat) | ||||||
|  |     { | ||||||
|  |         mRepeat = repeat; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void ScreenFader::queue(float time, float targetAlpha) | ||||||
|  |     { | ||||||
|  |         if (time < 0.f) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         if (time == 0.f) | ||||||
|  |         { | ||||||
|  |             mCurrentAlpha = targetAlpha; | ||||||
|  |             applyAlpha(); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         mQueue.push_back(FadeOp::Ptr(new FadeOp(this, time, targetAlpha))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool ScreenFader::isEmpty() | ||||||
|  |     { | ||||||
|  |         return mQueue.empty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void ScreenFader::clearQueue() | ||||||
|  |     { | ||||||
|  |         mQueue.clear(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void ScreenFader::notifyAlphaChanged(float alpha) | ||||||
|  |     { | ||||||
|  |         if (mCurrentAlpha == alpha) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         mCurrentAlpha = alpha; | ||||||
|  | 
 | ||||||
|  |         if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f) | ||||||
|  |             mMainWidget->setVisible(false); | ||||||
|  |         else | ||||||
|  |             applyAlpha(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void ScreenFader::notifyOperationFinished() | ||||||
|  |     { | ||||||
|  |         FadeOp::Ptr op = mQueue.front(); | ||||||
|  |         mQueue.pop_front(); | ||||||
|  | 
 | ||||||
|  |         if (mRepeat) | ||||||
|  |             mQueue.push_back(op); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     float ScreenFader::getCurrentAlpha() | ||||||
|  |     { | ||||||
|  |         return mCurrentAlpha; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,15 +1,44 @@ | ||||||
| #ifndef OPENMW_MWGUI_SCREENFADER_H | #ifndef OPENMW_MWGUI_SCREENFADER_H | ||||||
| #define OPENMW_MWGUI_SCREENFADER_H | #define OPENMW_MWGUI_SCREENFADER_H | ||||||
| 
 | 
 | ||||||
|  | #include <deque> | ||||||
|  | 
 | ||||||
|  | #include <boost/shared_ptr.hpp> | ||||||
|  | 
 | ||||||
| #include "windowbase.hpp" | #include "windowbase.hpp" | ||||||
| 
 | 
 | ||||||
| namespace MWGui | namespace MWGui | ||||||
| { | { | ||||||
|  |     class ScreenFader; | ||||||
|  | 
 | ||||||
|  |     class FadeOp | ||||||
|  |     { | ||||||
|  |     public: | ||||||
|  |         typedef boost::shared_ptr<FadeOp> Ptr; | ||||||
|  | 
 | ||||||
|  |         FadeOp(ScreenFader * fader, float time, float targetAlpha); | ||||||
|  | 
 | ||||||
|  |         bool isRunning(); | ||||||
|  | 
 | ||||||
|  |         void start(); | ||||||
|  |         void update(float dt); | ||||||
|  |         void finish(); | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         ScreenFader * mFader; | ||||||
|  |         float mRemainingTime; | ||||||
|  |         float mTargetTime; | ||||||
|  |         float mTargetAlpha; | ||||||
|  |         float mStartAlpha; | ||||||
|  |         bool mRunning; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     class ScreenFader : public WindowBase |     class ScreenFader : public WindowBase | ||||||
|     { |     { | ||||||
|     public: |     public: | ||||||
|         ScreenFader(); |         ScreenFader(const std::string & texturePath); | ||||||
|  | 
 | ||||||
|  |         void setTexture(const std::string & texturePath); | ||||||
| 
 | 
 | ||||||
|         void update(float dt); |         void update(float dt); | ||||||
| 
 | 
 | ||||||
|  | @ -18,27 +47,25 @@ namespace MWGui | ||||||
|         void fadeTo(const int percent, const float time); |         void fadeTo(const int percent, const float time); | ||||||
| 
 | 
 | ||||||
|         void setFactor (float factor); |         void setFactor (float factor); | ||||||
|  |         void setRepeat(bool repeat); | ||||||
|  | 
 | ||||||
|  |         void queue(float time, float targetAlpha); | ||||||
|  |         bool isEmpty(); | ||||||
|  |         void clearQueue(); | ||||||
|  | 
 | ||||||
|  |         void notifyAlphaChanged(float alpha); | ||||||
|  |         void notifyOperationFinished(); | ||||||
|  |         float getCurrentAlpha(); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         enum FadingMode |  | ||||||
|         { |  | ||||||
|             FadingMode_In, |  | ||||||
|             FadingMode_Out |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         void applyAlpha(); |         void applyAlpha(); | ||||||
| 
 | 
 | ||||||
|         FadingMode mMode; |  | ||||||
| 
 |  | ||||||
|         float mRemainingTime; |  | ||||||
|         float mTargetTime; |  | ||||||
|         float mTargetAlpha; |  | ||||||
|         float mCurrentAlpha; |         float mCurrentAlpha; | ||||||
|         float mStartAlpha; |  | ||||||
| 
 |  | ||||||
|         float mFactor; |         float mFactor; | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|  |         bool mRepeat; // repeat queued operations without removing them
 | ||||||
|  |         std::deque<FadeOp::Ptr> mQueue; | ||||||
|  |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -120,6 +120,9 @@ namespace MWGui | ||||||
|       , mCompanionWindow(NULL) |       , mCompanionWindow(NULL) | ||||||
|       , mVideoBackground(NULL) |       , mVideoBackground(NULL) | ||||||
|       , mVideoWidget(NULL) |       , mVideoWidget(NULL) | ||||||
|  |       , mWerewolfFader(NULL) | ||||||
|  |       , mBlindnessFader(NULL) | ||||||
|  |       , mHitFader(NULL) | ||||||
|       , mScreenFader(NULL) |       , mScreenFader(NULL) | ||||||
|       , mDebugWindow(NULL) |       , mDebugWindow(NULL) | ||||||
|       , mTranslationDataStorage (translationDataStorage) |       , mTranslationDataStorage (translationDataStorage) | ||||||
|  | @ -127,6 +130,8 @@ namespace MWGui | ||||||
|       , mInputBlocker(NULL) |       , mInputBlocker(NULL) | ||||||
|       , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) |       , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) | ||||||
|       , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) |       , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) | ||||||
|  |       , mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI")) | ||||||
|  |       , mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI")) | ||||||
|       , mHudEnabled(true) |       , mHudEnabled(true) | ||||||
|       , mGuiEnabled(true) |       , mGuiEnabled(true) | ||||||
|       , mCursorVisible(true) |       , mCursorVisible(true) | ||||||
|  | @ -267,7 +272,17 @@ namespace MWGui | ||||||
|         mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); |         mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); | ||||||
|         mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); |         mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); | ||||||
|         trackWindow(mCompanionWindow, "companion"); |         trackWindow(mCompanionWindow, "companion"); | ||||||
|         mScreenFader = new ScreenFader(); | 
 | ||||||
|  |         mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds"); | ||||||
|  |         mBlindnessFader = new ScreenFader("black.png"); | ||||||
|  |         std::string hitFaderTexture = "textures\\bm_player_hit_01.dds"; | ||||||
|  |         // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available
 | ||||||
|  |         // TODO: check if non-BM versions actually use player_hit_01.dds
 | ||||||
|  |         if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(hitFaderTexture)) | ||||||
|  |             hitFaderTexture = "textures\\player_hit_01.dds"; | ||||||
|  |         mHitFader = new ScreenFader(hitFaderTexture); | ||||||
|  |         mScreenFader = new ScreenFader("black.png"); | ||||||
|  | 
 | ||||||
|         mDebugWindow = new DebugWindow(); |         mDebugWindow = new DebugWindow(); | ||||||
| 
 | 
 | ||||||
|         mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); |         mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); | ||||||
|  | @ -359,6 +374,8 @@ namespace MWGui | ||||||
|         delete mCursorManager; |         delete mCursorManager; | ||||||
|         delete mRecharge; |         delete mRecharge; | ||||||
|         delete mCompanionWindow; |         delete mCompanionWindow; | ||||||
|  |         delete mHitFader; | ||||||
|  |         delete mWerewolfFader; | ||||||
|         delete mScreenFader; |         delete mScreenFader; | ||||||
|         delete mDebugWindow; |         delete mDebugWindow; | ||||||
| 
 | 
 | ||||||
|  | @ -862,6 +879,9 @@ namespace MWGui | ||||||
|         mConsole->checkReferenceAvailable(); |         mConsole->checkReferenceAvailable(); | ||||||
|         mCompanionWindow->onFrame(); |         mCompanionWindow->onFrame(); | ||||||
| 
 | 
 | ||||||
|  |         mWerewolfFader->update(frameDuration); | ||||||
|  |         mBlindnessFader->update(frameDuration); | ||||||
|  |         mHitFader->update(frameDuration); | ||||||
|         mScreenFader->update(frameDuration); |         mScreenFader->update(frameDuration); | ||||||
| 
 | 
 | ||||||
|         mDebugWindow->onFrame(frameDuration); |         mDebugWindow->onFrame(frameDuration); | ||||||
|  | @ -1450,7 +1470,10 @@ namespace MWGui | ||||||
| 
 | 
 | ||||||
|         const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); |         const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); | ||||||
|         if (player.getClass().getNpcStats(player).isWerewolf()) |         if (player.getClass().getNpcStats(player).isWerewolf()) | ||||||
|  |         { | ||||||
|  |             setWerewolfOverlay(true); | ||||||
|             forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); |             forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Remove this method for MyGUI 3.2.2
 |     // Remove this method for MyGUI 3.2.2
 | ||||||
|  | @ -1544,6 +1567,8 @@ namespace MWGui | ||||||
| 
 | 
 | ||||||
|         mForceHidden = GW_None; |         mForceHidden = GW_None; | ||||||
| 
 | 
 | ||||||
|  |         setWerewolfOverlay(false); | ||||||
|  | 
 | ||||||
|         mGuiModes.clear(); |         mGuiModes.clear(); | ||||||
|         MWBase::Environment::get().getInputManager()->changeInputMode(false); |         MWBase::Environment::get().getInputManager()->changeInputMode(false); | ||||||
|         updateVisible(); |         updateVisible(); | ||||||
|  | @ -1718,22 +1743,46 @@ namespace MWGui | ||||||
| 
 | 
 | ||||||
|     void WindowManager::fadeScreenIn(const float time) |     void WindowManager::fadeScreenIn(const float time) | ||||||
|     { |     { | ||||||
|         mScreenFader->fadeIn(time); |         mScreenFader->clearQueue(); | ||||||
|  |         mScreenFader->fadeOut(time); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void WindowManager::fadeScreenOut(const float time) |     void WindowManager::fadeScreenOut(const float time) | ||||||
|     { |     { | ||||||
|         mScreenFader->fadeOut(time); |         mScreenFader->clearQueue(); | ||||||
|  |         mScreenFader->fadeIn(time); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void WindowManager::fadeScreenTo(const int percent, const float time) |     void WindowManager::fadeScreenTo(const int percent, const float time) | ||||||
|     { |     { | ||||||
|  |         mScreenFader->clearQueue(); | ||||||
|         mScreenFader->fadeTo(percent, time); |         mScreenFader->fadeTo(percent, time); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void WindowManager::setScreenFactor(float factor) |     void WindowManager::setBlindness(const int percent) | ||||||
|     { |     { | ||||||
|         mScreenFader->setFactor(factor); |         mBlindnessFader->notifyAlphaChanged(percent / 100.f); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void WindowManager::activateHitOverlay(bool interrupt) | ||||||
|  |     { | ||||||
|  |         if (!mHitFaderEnabled) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         if (!interrupt && !mHitFader->isEmpty()) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         mHitFader->clearQueue(); | ||||||
|  |         mHitFader->fadeTo(100, 0.0f); | ||||||
|  |         mHitFader->fadeTo(0, 0.5f); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void WindowManager::setWerewolfOverlay(bool set) | ||||||
|  |     { | ||||||
|  |         if (!mWerewolfOverlayEnabled) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         mWerewolfFader->notifyAlphaChanged(set ? 1.0f : 0.0f); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) |     void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) | ||||||
|  |  | ||||||
|  | @ -330,8 +330,11 @@ namespace MWGui | ||||||
|     virtual void fadeScreenOut(const float time); |     virtual void fadeScreenOut(const float time); | ||||||
|     /// Fade the screen to a specified percentage of black, over \a time seconds
 |     /// Fade the screen to a specified percentage of black, over \a time seconds
 | ||||||
|     virtual void fadeScreenTo(const int percent, const float time); |     virtual void fadeScreenTo(const int percent, const float time); | ||||||
|     /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
 |     /// Darken the screen to a specified percentage
 | ||||||
|     virtual void setScreenFactor (float factor); |     virtual void setBlindness(const int percent); | ||||||
|  | 
 | ||||||
|  |     virtual void activateHitOverlay(bool interrupt); | ||||||
|  |     virtual void setWerewolfOverlay(bool set); | ||||||
| 
 | 
 | ||||||
|     virtual void toggleDebugWindow(); |     virtual void toggleDebugWindow(); | ||||||
| 
 | 
 | ||||||
|  | @ -387,6 +390,9 @@ namespace MWGui | ||||||
|     CompanionWindow* mCompanionWindow; |     CompanionWindow* mCompanionWindow; | ||||||
|     MyGUI::ImageBox* mVideoBackground; |     MyGUI::ImageBox* mVideoBackground; | ||||||
|     VideoWidget* mVideoWidget; |     VideoWidget* mVideoWidget; | ||||||
|  |     ScreenFader* mWerewolfFader; | ||||||
|  |     ScreenFader* mBlindnessFader; | ||||||
|  |     ScreenFader* mHitFader; | ||||||
|     ScreenFader* mScreenFader; |     ScreenFader* mScreenFader; | ||||||
|     DebugWindow* mDebugWindow; |     DebugWindow* mDebugWindow; | ||||||
| 
 | 
 | ||||||
|  | @ -398,6 +404,8 @@ namespace MWGui | ||||||
| 
 | 
 | ||||||
|     bool mCrosshairEnabled; |     bool mCrosshairEnabled; | ||||||
|     bool mSubtitlesEnabled; |     bool mSubtitlesEnabled; | ||||||
|  |     bool mHitFaderEnabled; | ||||||
|  |     bool mWerewolfOverlayEnabled; | ||||||
|     bool mHudEnabled; |     bool mHudEnabled; | ||||||
|     bool mGuiEnabled; |     bool mGuiEnabled; | ||||||
|     bool mCursorVisible; |     bool mCursorVisible; | ||||||
|  |  | ||||||
|  | @ -220,7 +220,7 @@ namespace MWMechanics | ||||||
|             // Use the smallest soulgem that is large enough to hold the soul
 |             // Use the smallest soulgem that is large enough to hold the soul
 | ||||||
|             MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster); |             MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster); | ||||||
|             MWWorld::ContainerStoreIterator gem = container.end(); |             MWWorld::ContainerStoreIterator gem = container.end(); | ||||||
|             float gemCapacity = std::numeric_limits<float>().max(); |             float gemCapacity = std::numeric_limits<float>::max(); | ||||||
|             std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
 |             std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
 | ||||||
|             for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); |             for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); | ||||||
|                  it != container.end(); ++it) |                  it != container.end(); ++it) | ||||||
|  | @ -585,6 +585,12 @@ namespace MWMechanics | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         bool receivedMagicDamage = false; | ||||||
|  | 
 | ||||||
|  |         if (creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth).getMagnitude() > 0.0f | ||||||
|  |                 || creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth).getMagnitude() > 0.0f) | ||||||
|  |             receivedMagicDamage = true; | ||||||
|  | 
 | ||||||
|         // Apply damage ticks
 |         // Apply damage ticks
 | ||||||
|         int damageEffects[] = { |         int damageEffects[] = { | ||||||
|             ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison, |             ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison, | ||||||
|  | @ -612,11 +618,22 @@ namespace MWMechanics | ||||||
|                 if (weather > 1) |                 if (weather > 1) | ||||||
|                     damageScale *= fMagicSunBlockedMult; |                     damageScale *= fMagicSunBlockedMult; | ||||||
|                 health.setCurrent(health.getCurrent() - magnitude * duration * damageScale); |                 health.setCurrent(health.getCurrent() - magnitude * duration * damageScale); | ||||||
|  | 
 | ||||||
|  |                 if (magnitude * damageScale > 0.0f) | ||||||
|  |                     receivedMagicDamage = true; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|  |             { | ||||||
|                 health.setCurrent(health.getCurrent() - magnitude * duration); |                 health.setCurrent(health.getCurrent() - magnitude * duration); | ||||||
| 
 | 
 | ||||||
|  |                 if (magnitude > 0.0f) | ||||||
|  |                     receivedMagicDamage = true; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         if (receivedMagicDamage && ptr.getRefData().getHandle() == "player") | ||||||
|  |             MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); | ||||||
|  | 
 | ||||||
|         creatureStats.setHealth(health); |         creatureStats.setHealth(health); | ||||||
| 
 | 
 | ||||||
|         if (!wasDead && creatureStats.isDead()) |         if (!wasDead && creatureStats.isDead()) | ||||||
|  | @ -875,13 +892,13 @@ namespace MWMechanics | ||||||
|                 static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat(); |                 static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat(); | ||||||
|                 ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration); |                 ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration); | ||||||
| 
 | 
 | ||||||
|                 // Play a drowning sound as necessary for the player
 |                 // Play a drowning sound
 | ||||||
|  |                 MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); | ||||||
|  |                 if(!sndmgr->getSoundPlaying(ptr, "drown")) | ||||||
|  |                     sndmgr->playSound3D(ptr, "drown", 1.0f, 1.0f); | ||||||
|  | 
 | ||||||
|                 if(ptr == world->getPlayerPtr()) |                 if(ptr == world->getPlayerPtr()) | ||||||
|                 { |                     MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); | ||||||
|                     MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); |  | ||||||
|                     if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown")) |  | ||||||
|                         sndmgr->playSound("drown", 1.0f, 1.0f); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|  |  | ||||||
|  | @ -166,10 +166,18 @@ namespace MWMechanics | ||||||
|     { |     { | ||||||
|         const CreatureStats& stats = actor.getClass().getCreatureStats(actor); |         const CreatureStats& stats = actor.getClass().getCreatureStats(actor); | ||||||
| 
 | 
 | ||||||
|         // Never casting racial spells (ST_Power and F_Always)
 |         if (spell->mData.mType != ESM::Spell::ST_Spell) | ||||||
|         if (spell->mData.mType != ESM::Spell::ST_Spell || spell->mData.mFlags & ESM::Spell::F_Always) |  | ||||||
|             return 0.f; |             return 0.f; | ||||||
| 
 | 
 | ||||||
|  |         // Don't make use of racial bonus spells, like MW. Can be made optional later
 | ||||||
|  |         if (actor.getClass().isNpc()) | ||||||
|  |         { | ||||||
|  |             std::string raceid = actor.get<ESM::NPC>()->mBase->mRace; | ||||||
|  |             const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceid); | ||||||
|  |             if (race->mPowers.exists(spell->mId)) | ||||||
|  |                 return 0.f; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (spell->mData.mCost > stats.getMagicka().getCurrent()) |         if (spell->mData.mCost > stats.getMagicka().getCurrent()) | ||||||
|             return 0.f; |             return 0.f; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -292,6 +292,7 @@ namespace MWMechanics | ||||||
|         , mTarget(target) |         , mTarget(target) | ||||||
|         , mStack(false) |         , mStack(false) | ||||||
|         , mHitPosition(0,0,0) |         , mHitPosition(0,0,0) | ||||||
|  |         , mAlwaysSucceed(false) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -761,7 +762,7 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|         int school = 0; |         int school = 0; | ||||||
| 
 | 
 | ||||||
|         if (mCaster.getClass().isActor()) |         if (mCaster.getClass().isActor() && !mAlwaysSucceed) | ||||||
|         { |         { | ||||||
|             school = getSpellSchool(spell, mCaster); |             school = getSpellSchool(spell, mCaster); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -68,6 +68,7 @@ namespace MWMechanics | ||||||
|         std::string mId; // ID of spell, potion, item etc
 |         std::string mId; // ID of spell, potion, item etc
 | ||||||
|         std::string mSourceName; // Display name for spell, potion, etc
 |         std::string mSourceName; // Display name for spell, potion, etc
 | ||||||
|         Ogre::Vector3 mHitPosition; // Used for spawning area orb
 |         Ogre::Vector3 mHitPosition; // Used for spawning area orb
 | ||||||
|  |         bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false)
 | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target); |         CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target); | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ namespace MWRender | ||||||
|         mNode = renderRoot->createChildSceneNode(); |         mNode = renderRoot->createChildSceneNode(); | ||||||
| 
 | 
 | ||||||
|         mAnimation = new NpcAnimation(mCharacter, mNode, |         mAnimation = new NpcAnimation(mCharacter, mNode, | ||||||
|                                       0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); |                                       0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); | ||||||
| 
 | 
 | ||||||
|         Ogre::Vector3 scale = mNode->getScale(); |         Ogre::Vector3 scale = mNode->getScale(); | ||||||
|         mCamera->setPosition(mPosition * scale); |         mCamera->setPosition(mPosition * scale); | ||||||
|  | @ -118,7 +118,7 @@ namespace MWRender | ||||||
|         assert(mAnimation); |         assert(mAnimation); | ||||||
|         delete mAnimation; |         delete mAnimation; | ||||||
|         mAnimation = new NpcAnimation(mCharacter, mNode, |         mAnimation = new NpcAnimation(mCharacter, mNode, | ||||||
|                                       0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); |                                       0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); | ||||||
| 
 | 
 | ||||||
|         float scale=1.f; |         float scale=1.f; | ||||||
|         mCharacter.getClass().adjustScale(mCharacter, scale); |         mCharacter.getClass().adjustScale(mCharacter, scale); | ||||||
|  |  | ||||||
|  | @ -177,7 +177,7 @@ NpcAnimation::~NpcAnimation() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, ViewMode viewMode) | NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, bool disableSounds, ViewMode viewMode) | ||||||
|   : Animation(ptr, node), |   : Animation(ptr, node), | ||||||
|     mVisibilityFlags(visibilityFlags), |     mVisibilityFlags(visibilityFlags), | ||||||
|     mListenerDisabled(disableListener), |     mListenerDisabled(disableListener), | ||||||
|  | @ -186,7 +186,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v | ||||||
|     mShowCarriedLeft(true), |     mShowCarriedLeft(true), | ||||||
|     mFirstPersonOffset(0.f, 0.f, 0.f), |     mFirstPersonOffset(0.f, 0.f, 0.f), | ||||||
|     mAlpha(1.f), |     mAlpha(1.f), | ||||||
|     mNpcType(Type_Normal) |     mNpcType(Type_Normal), | ||||||
|  |     mSoundsDisabled(disableSounds) | ||||||
| { | { | ||||||
|     mNpc = mPtr.get<ESM::NPC>()->mBase; |     mNpc = mPtr.get<ESM::NPC>()->mBase; | ||||||
| 
 | 
 | ||||||
|  | @ -297,7 +298,6 @@ void NpcAnimation::updateParts() | ||||||
| {     | {     | ||||||
|     mAlpha = 1.f; |     mAlpha = 1.f; | ||||||
|     const MWWorld::Class &cls = mPtr.getClass(); |     const MWWorld::Class &cls = mPtr.getClass(); | ||||||
|     MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); |  | ||||||
| 
 | 
 | ||||||
|     NpcType curType = Type_Normal; |     NpcType curType = Type_Normal; | ||||||
|     if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0) |     if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0) | ||||||
|  | @ -334,6 +334,7 @@ void NpcAnimation::updateParts() | ||||||
|     }; |     }; | ||||||
|     static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); |     static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); | ||||||
| 
 | 
 | ||||||
|  |     MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); | ||||||
|     for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) |     for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) | ||||||
|     { |     { | ||||||
|         MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); |         MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); | ||||||
|  | @ -625,6 +626,11 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) | ||||||
|     mPartslots[type] = -1; |     mPartslots[type] = -1; | ||||||
| 
 | 
 | ||||||
|     mObjectParts[type].setNull(); |     mObjectParts[type].setNull(); | ||||||
|  |     if (!mSoundIds[type].empty() && !mSoundsDisabled) | ||||||
|  |     { | ||||||
|  |         MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]); | ||||||
|  |         mSoundIds[type].clear(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority) | void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority) | ||||||
|  | @ -654,8 +660,22 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g | ||||||
|     removeIndividualPart(type); |     removeIndividualPart(type); | ||||||
|     mPartslots[type] = group; |     mPartslots[type] = group; | ||||||
|     mPartPriorities[type] = priority; |     mPartPriorities[type] = priority; | ||||||
| 
 |  | ||||||
|     mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor); |     mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor); | ||||||
|  | 
 | ||||||
|  |     if (!mSoundsDisabled) | ||||||
|  |     { | ||||||
|  |         MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); | ||||||
|  |         MWWorld::ContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); | ||||||
|  |         if (csi != inv.end()) | ||||||
|  |         { | ||||||
|  |             mSoundIds[type] = csi->getClass().getSound(*csi); | ||||||
|  |             if (!mSoundIds[type].empty()) | ||||||
|  |             { | ||||||
|  |                 MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, | ||||||
|  |                     MWBase::SoundManager::Play_Loop); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     if(mObjectParts[type]->mSkelBase) |     if(mObjectParts[type]->mSkelBase) | ||||||
|     { |     { | ||||||
|         Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); |         Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); | ||||||
|  | @ -760,7 +780,7 @@ void NpcAnimation::showWeapons(bool showWeapon) | ||||||
|     mShowWeapons = showWeapon; |     mShowWeapons = showWeapon; | ||||||
|     if(showWeapon) |     if(showWeapon) | ||||||
|     { |     { | ||||||
|         MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); |         MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); | ||||||
|         MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); |         MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); | ||||||
|         if(weapon != inv.end()) |         if(weapon != inv.end()) | ||||||
|         { |         { | ||||||
|  | @ -793,9 +813,8 @@ void NpcAnimation::showWeapons(bool showWeapon) | ||||||
| void NpcAnimation::showCarriedLeft(bool show) | void NpcAnimation::showCarriedLeft(bool show) | ||||||
| { | { | ||||||
|     mShowCarriedLeft = show; |     mShowCarriedLeft = show; | ||||||
|     MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); |     MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); | ||||||
|     MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); |     MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); | ||||||
| 
 |  | ||||||
|     if(show && iter != inv.end()) |     if(show && iter != inv.end()) | ||||||
|     { |     { | ||||||
|         Ogre::Vector3 glowColor = getEnchantmentColor(*iter); |         Ogre::Vector3 glowColor = getEnchantmentColor(*iter); | ||||||
|  | @ -928,4 +947,9 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void NpcAnimation::equipmentChanged() | ||||||
|  | { | ||||||
|  |     updateParts(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -51,7 +51,7 @@ public: | ||||||
| class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener | class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     virtual void equipmentChanged() { updateParts(); } |     virtual void equipmentChanged(); | ||||||
|     virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); |     virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | @ -70,6 +70,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     // Bounded Parts
 |     // Bounded Parts
 | ||||||
|     NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count]; |     NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count]; | ||||||
|  |     std::string mSoundIds[ESM::PRT_Count]; | ||||||
| 
 | 
 | ||||||
|     const ESM::NPC *mNpc; |     const ESM::NPC *mNpc; | ||||||
|     std::string    mHeadModel; |     std::string    mHeadModel; | ||||||
|  | @ -97,6 +98,7 @@ private: | ||||||
|     Ogre::SharedPtr<WeaponAnimationTime> mWeaponAnimationTime; |     Ogre::SharedPtr<WeaponAnimationTime> mWeaponAnimationTime; | ||||||
| 
 | 
 | ||||||
|     float mAlpha; |     float mAlpha; | ||||||
|  |     bool mSoundsDisabled; | ||||||
| 
 | 
 | ||||||
|     void updateNpcBase(); |     void updateNpcBase(); | ||||||
| 
 | 
 | ||||||
|  | @ -123,10 +125,11 @@ public: | ||||||
|      *                         one listener at a time, so you shouldn't do this if creating several NpcAnimations |      *                         one listener at a time, so you shouldn't do this if creating several NpcAnimations | ||||||
|      *                         for the same Ptr, eg preview dolls for the player. |      *                         for the same Ptr, eg preview dolls for the player. | ||||||
|      *                         Those need to be manually rendered anyway. |      *                         Those need to be manually rendered anyway. | ||||||
|  |      * @param disableSounds    Same as \a disableListener but for playing items sounds | ||||||
|      * @param viewMode |      * @param viewMode | ||||||
|      */ |      */ | ||||||
|     NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener = false, |     NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener = false, | ||||||
|                  ViewMode viewMode=VM_Normal); |                  bool disableSounds = false, ViewMode viewMode=VM_Normal); | ||||||
|     virtual ~NpcAnimation(); |     virtual ~NpcAnimation(); | ||||||
| 
 | 
 | ||||||
|     virtual void enableHeadAnimation(bool enable); |     virtual void enableHeadAnimation(bool enable); | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ | ||||||
| #include "../mwbase/statemanager.hpp" | #include "../mwbase/statemanager.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../mwmechanics/creaturestats.hpp" | #include "../mwmechanics/creaturestats.hpp" | ||||||
|  | #include "../mwmechanics/npcstats.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../mwworld/ptr.hpp" | #include "../mwworld/ptr.hpp" | ||||||
| 
 | 
 | ||||||
|  | @ -346,9 +347,12 @@ void RenderingManager::update (float duration, bool paused) | ||||||
|     MWWorld::Ptr player = world->getPlayerPtr(); |     MWWorld::Ptr player = world->getPlayerPtr(); | ||||||
| 
 | 
 | ||||||
|     int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); |     int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); | ||||||
|     MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f))); |     MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind))); | ||||||
|     setAmbientMode(); |     setAmbientMode(); | ||||||
| 
 | 
 | ||||||
|  |     if (player.getClass().getNpcStats(player).isWerewolf()) | ||||||
|  |         MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mCamera->isFirstPerson()); | ||||||
|  | 
 | ||||||
|     // player position
 |     // player position
 | ||||||
|     MWWorld::RefData &data = player.getRefData(); |     MWWorld::RefData &data = player.getRefData(); | ||||||
|     Ogre::Vector3 playerPos(data.getPosition().pos); |     Ogre::Vector3 playerPos(data.getPosition().pos); | ||||||
|  | @ -511,7 +515,7 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue | ||||||
|     if (density == 0) |     if (density == 0) | ||||||
|     { |     { | ||||||
|         mFogStart = 0; |         mFogStart = 0; | ||||||
|         mFogEnd = std::numeric_limits<float>().max(); |         mFogEnd = std::numeric_limits<float>::max(); | ||||||
|         mRendering.getCamera()->setFarClipDistance (max); |         mRendering.getCamera()->setFarClipDistance (max); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|  |  | ||||||
|  | @ -153,7 +153,7 @@ namespace MWScript | ||||||
|                     if (cell->getCell()->hasWater()) |                     if (cell->getCell()->hasWater()) | ||||||
|                         runtime.push (cell->getWaterLevel()); |                         runtime.push (cell->getWaterLevel()); | ||||||
|                     else |                     else | ||||||
|                         runtime.push (-std::numeric_limits<float>().max()); |                         runtime.push (-std::numeric_limits<float>::max()); | ||||||
|                 } |                 } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -438,7 +438,7 @@ namespace MWScript | ||||||
| 
 | 
 | ||||||
|         // If the objects are in different worldspaces, return a large value (just like vanilla)
 |         // If the objects are in different worldspaces, return a large value (just like vanilla)
 | ||||||
|         if (ref.getCell()->getCell()->getCellId().mWorldspace != ref2.getCell()->getCell()->getCellId().mWorldspace) |         if (ref.getCell()->getCell()->getCellId().mWorldspace != ref2.getCell()->getCell()->getCellId().mWorldspace) | ||||||
|             return std::numeric_limits<float>().max(); |             return std::numeric_limits<float>::max(); | ||||||
| 
 | 
 | ||||||
|         double diff[3]; |         double diff[3]; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -854,6 +854,7 @@ namespace MWScript | ||||||
| 
 | 
 | ||||||
|                 MWMechanics::CastSpell cast(ptr, target); |                 MWMechanics::CastSpell cast(ptr, target); | ||||||
|                 cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); |                 cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); | ||||||
|  |                 cast.mAlwaysSucceed = true; | ||||||
|                 cast.cast(spell); |                 cast.cast(spell); | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|  | @ -871,6 +872,7 @@ namespace MWScript | ||||||
| 
 | 
 | ||||||
|                 MWMechanics::CastSpell cast(ptr, ptr); |                 MWMechanics::CastSpell cast(ptr, ptr); | ||||||
|                 cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos); |                 cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos); | ||||||
|  |                 cast.mAlwaysSucceed = true; | ||||||
|                 cast.cast(spell); |                 cast.cast(spell); | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ namespace MWSound | ||||||
|                 else if (type == SampleType_Int16) |                 else if (type == SampleType_Int16) | ||||||
|                 { |                 { | ||||||
|                     value = *reinterpret_cast<const Ogre::int16*>(&data[sample*advance]); |                     value = *reinterpret_cast<const Ogre::int16*>(&data[sample*advance]); | ||||||
|                     value /= float(std::numeric_limits<Ogre::int16>().max()); |                     value /= float(std::numeric_limits<Ogre::int16>::max()); | ||||||
|                 } |                 } | ||||||
|                 else if (type == SampleType_Float32) |                 else if (type == SampleType_Float32) | ||||||
|                 { |                 { | ||||||
|  |  | ||||||
|  | @ -454,6 +454,7 @@ namespace MWSound | ||||||
|         while(snditer != mActiveSounds.end()) |         while(snditer != mActiveSounds.end()) | ||||||
|         { |         { | ||||||
|             if(snditer->second.first != MWWorld::Ptr() && |             if(snditer->second.first != MWWorld::Ptr() && | ||||||
|  |                snditer->second.first.getCellRef().getRefId() != "player" && | ||||||
|                snditer->second.first.getCell() == cell) |                snditer->second.first.getCell() == cell) | ||||||
|             { |             { | ||||||
|                 snditer->first->stop(); |                 snditer->first->stop(); | ||||||
|  |  | ||||||
|  | @ -429,4 +429,9 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|         return getEncumbrance(ptr) / capacity; |         return getEncumbrance(ptr) / capacity; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     std::string Class::getSound(const MWWorld::Ptr&) const | ||||||
|  |     { | ||||||
|  |       return std::string(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -339,6 +339,9 @@ namespace MWWorld | ||||||
|             virtual void respawn (const MWWorld::Ptr& ptr) const {} |             virtual void respawn (const MWWorld::Ptr& ptr) const {} | ||||||
| 
 | 
 | ||||||
|             virtual void restock (const MWWorld::Ptr& ptr) const {} |             virtual void restock (const MWWorld::Ptr& ptr) const {} | ||||||
|  | 
 | ||||||
|  |             /// Returns sound id
 | ||||||
|  |             virtual std::string getSound(const MWWorld::Ptr& ptr) const; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -148,16 +148,18 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite | ||||||
|     flagAsModified(); |     flagAsModified(); | ||||||
| 
 | 
 | ||||||
|     fireEquipmentChangedEvent(); |     fireEquipmentChangedEvent(); | ||||||
|  | 
 | ||||||
|     updateMagicEffects(actor); |     updateMagicEffects(actor); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) | void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) | ||||||
| { | { | ||||||
|     // Only *one* change event should be fired
 |  | ||||||
|     mUpdatesEnabled = false; |     mUpdatesEnabled = false; | ||||||
|     for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) |     for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) | ||||||
|         unequipSlot(slot, actor); |         unequipSlot(slot, actor); | ||||||
|  | 
 | ||||||
|     mUpdatesEnabled = true; |     mUpdatesEnabled = true; | ||||||
|  | 
 | ||||||
|     fireEquipmentChangedEvent(); |     fireEquipmentChangedEvent(); | ||||||
|     updateMagicEffects(actor); |     updateMagicEffects(actor); | ||||||
| } | } | ||||||
|  | @ -204,8 +206,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) | ||||||
|         if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && |         if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && | ||||||
|                 (actor.getClass().getScript(actor).empty() || |                 (actor.getClass().getScript(actor).empty() || | ||||||
|                 !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) |                 !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) | ||||||
|  |         { | ||||||
|             continue; |             continue; | ||||||
| 
 |         } | ||||||
|         int testSkill = test.getClass().getEquipmentSkill (test); |         int testSkill = test.getClass().getEquipmentSkill (test); | ||||||
| 
 | 
 | ||||||
|         std::pair<std::vector<int>, bool> itemsSlots = |         std::pair<std::vector<int>, bool> itemsSlots = | ||||||
|  | @ -277,11 +280,13 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) | ||||||
|     bool changed = false; |     bool changed = false; | ||||||
| 
 | 
 | ||||||
|     for (std::size_t i=0; i<slots_.size(); ++i) |     for (std::size_t i=0; i<slots_.size(); ++i) | ||||||
|         if (slots_[i]!=mSlots[i]) |     { | ||||||
|  |         if (slots_[i] != mSlots[i]) | ||||||
|         { |         { | ||||||
|             changed = true; |             changed = true; | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
| 
 |     } | ||||||
|     mUpdatesEnabled = true; |     mUpdatesEnabled = true; | ||||||
| 
 | 
 | ||||||
|     if (changed) |     if (changed) | ||||||
|  |  | ||||||
|  | @ -829,15 +829,15 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt) |     const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt) | ||||||
|     { |     { | ||||||
|         // Collision events are only tracked for a single frame, so reset first
 |  | ||||||
|         mCollisions.clear(); |  | ||||||
|         mStandingCollisions.clear(); |  | ||||||
| 
 |  | ||||||
|         mMovementResults.clear(); |         mMovementResults.clear(); | ||||||
| 
 | 
 | ||||||
|         mTimeAccum += dt; |         mTimeAccum += dt; | ||||||
|         if(mTimeAccum >= 1.0f/60.0f) |         if(mTimeAccum >= 1.0f/60.0f) | ||||||
|         { |         { | ||||||
|  |             // Collision events should be available on every frame
 | ||||||
|  |             mCollisions.clear(); | ||||||
|  |             mStandingCollisions.clear(); | ||||||
|  | 
 | ||||||
|             const MWBase::World *world = MWBase::Environment::get().getWorld(); |             const MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
|             PtrVelocityList::iterator iter = mMovementQueue.begin(); |             PtrVelocityList::iterator iter = mMovementQueue.begin(); | ||||||
|             for(;iter != mMovementQueue.end();++iter) |             for(;iter != mMovementQueue.end();++iter) | ||||||
|  |  | ||||||
|  | @ -124,10 +124,10 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     void Scene::getGridCenter(int &cellX, int &cellY) |     void Scene::getGridCenter(int &cellX, int &cellY) | ||||||
|     { |     { | ||||||
|         int maxX = std::numeric_limits<int>().min(); |         int maxX = std::numeric_limits<int>::min(); | ||||||
|         int maxY = std::numeric_limits<int>().min(); |         int maxY = std::numeric_limits<int>::min(); | ||||||
|         int minX = std::numeric_limits<int>().max(); |         int minX = std::numeric_limits<int>::max(); | ||||||
|         int minY = std::numeric_limits<int>().max(); |         int minY = std::numeric_limits<int>::max(); | ||||||
|         CellStoreCollection::iterator iter = mActiveCells.begin(); |         CellStoreCollection::iterator iter = mActiveCells.begin(); | ||||||
|         while (iter!=mActiveCells.end()) |         while (iter!=mActiveCells.end()) | ||||||
|         { |         { | ||||||
|  |  | ||||||
|  | @ -2078,6 +2078,9 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     void World::hurtStandingActors(const Ptr &object, float healthPerSecond) |     void World::hurtStandingActors(const Ptr &object, float healthPerSecond) | ||||||
|     { |     { | ||||||
|  |         if (MWBase::Environment::get().getWindowManager()->isGuiMode()) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|         std::vector<std::string> actors; |         std::vector<std::string> actors; | ||||||
|         mPhysics->getActorsStandingOn(object, actors); |         mPhysics->getActorsStandingOn(object, actors); | ||||||
|         for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it) |         for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it) | ||||||
|  | @ -2087,14 +2090,28 @@ namespace MWWorld | ||||||
|                 continue; |                 continue; | ||||||
| 
 | 
 | ||||||
|             MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); |             MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); | ||||||
|  |             if (stats.isDead()) | ||||||
|  |                 continue; | ||||||
|             MWMechanics::DynamicStat<float> health = stats.getHealth(); |             MWMechanics::DynamicStat<float> health = stats.getHealth(); | ||||||
|             health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); |             health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); | ||||||
|             stats.setHealth(health); |             stats.setHealth(health); | ||||||
|  | 
 | ||||||
|  |             if (healthPerSecond > 0.0f) | ||||||
|  |             { | ||||||
|  |                 if (actor.getRefData().getHandle() == "player") | ||||||
|  |                     MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); | ||||||
|  | 
 | ||||||
|  |                 if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) | ||||||
|  |                     MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void World::hurtCollidingActors(const Ptr &object, float healthPerSecond) |     void World::hurtCollidingActors(const Ptr &object, float healthPerSecond) | ||||||
|     { |     { | ||||||
|  |         if (MWBase::Environment::get().getWindowManager()->isGuiMode()) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|         std::vector<std::string> actors; |         std::vector<std::string> actors; | ||||||
|         mPhysics->getActorsCollidingWith(object, actors); |         mPhysics->getActorsCollidingWith(object, actors); | ||||||
|         for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it) |         for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it) | ||||||
|  | @ -2104,9 +2121,20 @@ namespace MWWorld | ||||||
|                 continue; |                 continue; | ||||||
| 
 | 
 | ||||||
|             MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); |             MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); | ||||||
|  |             if (stats.isDead()) | ||||||
|  |                 continue; | ||||||
|             MWMechanics::DynamicStat<float> health = stats.getHealth(); |             MWMechanics::DynamicStat<float> health = stats.getHealth(); | ||||||
|             health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); |             health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); | ||||||
|             stats.setHealth(health); |             stats.setHealth(health); | ||||||
|  | 
 | ||||||
|  |             if (healthPerSecond > 0.0f) | ||||||
|  |             { | ||||||
|  |                 if (actor.getRefData().getHandle() == "player") | ||||||
|  |                     MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); | ||||||
|  | 
 | ||||||
|  |                 if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) | ||||||
|  |                     MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -2353,6 +2381,8 @@ namespace MWWorld | ||||||
|                 windowManager->unsetForceHide(MWGui::GW_Magic); |                 windowManager->unsetForceHide(MWGui::GW_Magic); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             windowManager->setWerewolfOverlay(werewolf); | ||||||
|  | 
 | ||||||
|             // Witnesses of the player's transformation will make them a globally known werewolf
 |             // Witnesses of the player's transformation will make them a globally known werewolf
 | ||||||
|             std::vector<MWWorld::Ptr> closeActors; |             std::vector<MWWorld::Ptr> closeActors; | ||||||
|             MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(actor.getRefData().getPosition().pos), |             MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(actor.getRefData().getPosition().pos), | ||||||
|  | @ -2934,6 +2964,9 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition) |     void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition) | ||||||
|     { |     { | ||||||
|  |         if (ptr.getRefData().getHandle() == "player" && Settings::Manager::getBool("hit fader", "GUI")) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|         int type = ptr.getClass().getBloodTexture(ptr); |         int type = ptr.getClass().getBloodTexture(ptr); | ||||||
|         std::string texture; |         std::string texture; | ||||||
|         switch (type) |         switch (type) | ||||||
|  |  | ||||||
|  | @ -34,8 +34,8 @@ namespace ESMTerrain | ||||||
|         if (!land) |         if (!land) | ||||||
|             return false; |             return false; | ||||||
| 
 | 
 | ||||||
|         min = std::numeric_limits<float>().max(); |         min = std::numeric_limits<float>::max(); | ||||||
|         max = -std::numeric_limits<float>().max(); |         max = -std::numeric_limits<float>::max(); | ||||||
|         for (int row=0; row<ESM::Land::LAND_SIZE; ++row) |         for (int row=0; row<ESM::Land::LAND_SIZE; ++row) | ||||||
|         { |         { | ||||||
|             for (int col=0; col<ESM::Land::LAND_SIZE; ++col) |             for (int col=0; col<ESM::Land::LAND_SIZE; ++col) | ||||||
|  |  | ||||||
|  | @ -15,8 +15,8 @@ namespace Gui | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         NumericEditBox() |         NumericEditBox() | ||||||
|             : mValue(0), mMinValue(std::numeric_limits<int>().min()), |             : mValue(0), mMinValue(std::numeric_limits<int>::min()), | ||||||
|             mMaxValue(std::numeric_limits<int>().max()) |             mMaxValue(std::numeric_limits<int>::max()) | ||||||
|         {} |         {} | ||||||
| 
 | 
 | ||||||
|         void initialiseOverride(); |         void initialiseOverride(); | ||||||
|  |  | ||||||
|  | @ -94,6 +94,7 @@ Thomas Luppi (Digmaster) | ||||||
| Tom Mason (wheybags) | Tom Mason (wheybags) | ||||||
| Torben Leif Carrington (TorbenC) | Torben Leif Carrington (TorbenC) | ||||||
| Vincent Heuken | Vincent Heuken | ||||||
|  | vocollapse | ||||||
| 
 | 
 | ||||||
| Packagers: | Packagers: | ||||||
| Alexander Olofsson (Ace) - Windows | Alexander Olofsson (Ace) - Windows | ||||||
|  |  | ||||||
|  | @ -58,7 +58,7 @@ PROJECT_LOGO           = | ||||||
| # entered, it will be relative to the location where doxygen was started. If | # entered, it will be relative to the location where doxygen was started. If | ||||||
| # left blank the current directory will be used. | # left blank the current directory will be used. | ||||||
| 
 | 
 | ||||||
| OUTPUT_DIRECTORY       = Doxygen | OUTPUT_DIRECTORY       = @OpenMW_BINARY_DIR@/docs/Doxygen | ||||||
| 
 | 
 | ||||||
| # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- | # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- | ||||||
| # directories (in 2 levels) under the output directory of each output format and | # directories (in 2 levels) under the output directory of each output format and | ||||||
|  | @ -764,10 +764,10 @@ WARN_LOGFILE           = | ||||||
| # spaces. | # spaces. | ||||||
| # Note: If this tag is empty the current directory is searched. | # Note: If this tag is empty the current directory is searched. | ||||||
| 
 | 
 | ||||||
| INPUT                  = apps \ | INPUT                  = @OpenMW_SOURCE_DIR@/apps \ | ||||||
|                          components \ |                          @OpenMW_SOURCE_DIR@/components \ | ||||||
|                          libs \ |                          @OpenMW_SOURCE_DIR@/libs \ | ||||||
|                          docs |                          @OpenMW_BINARY_DIR@/docs/mainpage.hpp | ||||||
| 
 | 
 | ||||||
| # This tag can be used to specify the character encoding of the source files | # This tag can be used to specify the character encoding of the source files | ||||||
| # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses | ||||||
|  | @ -38,7 +38,7 @@ PROJECT_NUMBER         = | ||||||
| # If a relative path is entered, it will be relative to the location | # If a relative path is entered, it will be relative to the location | ||||||
| # where doxygen was started. If left blank the current directory will be used. | # where doxygen was started. If left blank the current directory will be used. | ||||||
| 
 | 
 | ||||||
| OUTPUT_DIRECTORY       = ../doxygen | OUTPUT_DIRECTORY       = @DOXYGEN_PAGES_OUTPUT_DIR@ | ||||||
| 
 | 
 | ||||||
| # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create | # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create | ||||||
| # 4096 sub-directories (in 2 levels) under the output directory of each output | # 4096 sub-directories (in 2 levels) under the output directory of each output | ||||||
|  | @ -573,10 +573,10 @@ WARN_LOGFILE           = | ||||||
| # directories like "/usr/src/myproject". Separate the files or directories | # directories like "/usr/src/myproject". Separate the files or directories | ||||||
| # with spaces. | # with spaces. | ||||||
| 
 | 
 | ||||||
| INPUT                  = apps \ | INPUT                  = @OpenMW_SOURCE_DIR@/apps \ | ||||||
|                          components \ |                          @OpenMW_SOURCE_DIR@/components \ | ||||||
|                          libs \ |                          @OpenMW_SOURCE_DIR@/libs \ | ||||||
|                          docs |                          @OpenMW_BINARY_DIR@/docs/mainpage.hpp | ||||||
| 
 | 
 | ||||||
| # This tag can be used to specify the character encoding of the source files | # This tag can be used to specify the character encoding of the source files | ||||||
| # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is | # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is | ||||||
							
								
								
									
										6
									
								
								extern/sdl4ogre/sdlwindowhelper.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								extern/sdl4ogre/sdlwindowhelper.cpp
									
									
									
									
										vendored
									
									
								
							|  | @ -27,7 +27,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, | ||||||
| 		throw std::runtime_error("Couldn't get WM Info!"); | 		throw std::runtime_error("Couldn't get WM Info!"); | ||||||
| 
 | 
 | ||||||
| 	Ogre::String winHandle; | 	Ogre::String winHandle; | ||||||
| 	Ogre::String winHandleSurface; |  | ||||||
| 
 | 
 | ||||||
| 	switch (wmInfo.subsystem) | 	switch (wmInfo.subsystem) | ||||||
| 	{ | 	{ | ||||||
|  | @ -46,8 +45,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, | ||||||
| #elif ANDROID            | #elif ANDROID            | ||||||
|         case SDL_SYSWM_ANDROID: |         case SDL_SYSWM_ANDROID: | ||||||
| 		winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window); | 		winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window); | ||||||
| 		winHandleSurface = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.surface); |  | ||||||
|           |  | ||||||
| 		break; | 		break; | ||||||
|  #else |  #else | ||||||
| 	case SDL_SYSWM_X11: | 	case SDL_SYSWM_X11: | ||||||
|  | @ -63,7 +60,8 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, | ||||||
| 	/// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error.
 | 	/// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error.
 | ||||||
| 
 | 
 | ||||||
| #ifdef ANDROID	 | #ifdef ANDROID	 | ||||||
|         params.insert(std::make_pair("externalSurface",  winHandleSurface)); |         SDL_GLContext context= SDL_GL_CreateContext(window); | ||||||
|  |         params.insert(std::make_pair("currentGLContext","True")); | ||||||
| #endif | #endif | ||||||
|         params.insert(std::make_pair("externalWindowHandle",  winHandle)); |         params.insert(std::make_pair("externalWindowHandle",  winHandle)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,6 +41,9 @@ tooltip delay = 0 | ||||||
| 
 | 
 | ||||||
| subtitles = false | subtitles = false | ||||||
| 
 | 
 | ||||||
|  | hit fader = true | ||||||
|  | werewolf overlay = true | ||||||
|  | 
 | ||||||
| [General] | [General] | ||||||
| # Camera field of view | # Camera field of view | ||||||
| field of view = 55 | field of view = 55 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue