diff --git a/CMakeLists.txt b/CMakeLists.txt index 26bfcb5e1..1e9a4f1cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif (ANDROID) # 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(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE) @@ -837,3 +837,26 @@ if (APPLE) include(CPack) 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 () + diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c14caa7f7..0336f51db 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -77,12 +77,12 @@ opencs_units (view/widget opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget - previewwidget terrainstorage + previewwidget ) opencs_units_noqt (view/render navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight - lightingbright object cell textoverlay overlaymask + lightingbright object cell terrainstorage textoverlay overlaymask ) opencs_hdrs_noqt (view/render diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index be03f91a5..ab4325cfc 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -2,7 +2,8 @@ #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 diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 58fa221e6..bfc4f3b33 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -335,8 +335,11 @@ namespace MWBase virtual void fadeScreenOut(const float time) = 0; /// Fade the screen to a specified percentage of black, over \a time seconds 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. - virtual void setScreenFactor (float factor) = 0; + /// Darken the screen to a specified percentage + virtual void setBlindness(const int percent) = 0; + + virtual void activateHitOverlay(bool interrupt=true) = 0; + virtual void setWerewolfOverlay(bool set) = 0; virtual void toggleDebugWindow() = 0; }; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index eabebc72a..7b2d7e132 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -297,4 +297,9 @@ namespace MWClass state2.mTime = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; } + + std::string Light::getSound(const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mSound; + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 584039336..a3b841261 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -82,6 +82,8 @@ namespace MWClass virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const; ///< Write additional state from \a ptr into \a state. + + virtual std::string getSound(const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4149d31d3..d3f86c03b 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -24,6 +24,7 @@ #include "../mwmechanics/combat.hpp" #include "../mwmechanics/autocalcspell.hpp" #include "../mwmechanics/difficultyscaling.hpp" +#include "../mwmechanics/character.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" @@ -775,7 +776,11 @@ namespace MWClass damage = scaleDamage(damage, attacker, ptr); if(damage > 0.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; setActorHealth(ptr, health, attacker); } @@ -1216,60 +1221,43 @@ namespace MWClass 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(); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); if(world->isSwimming(ptr)) - return "Swim Left"; + return (name == "left") ? "Swim Left" : "Swim Right"; if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - return "FootWaterLeft"; + return (name == "left") ? "FootWaterLeft" : "FootWaterRight"; 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::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) - return "FootBareLeft"; + return (name == "left") ? "FootBareLeft" : "FootBareRight"; switch(boots->getClass().getEquipmentSkill(*boots)) { case ESM::Skill::LightArmor: - return "FootLightLeft"; + return (name == "left") ? "FootLightLeft" : "FootLightRight"; case ESM::Skill::MediumArmor: - return "FootMedLeft"; + return (name == "left") ? "FootMedLeft" : "FootMedRight"; case ESM::Skill::HeavyArmor: - return "FootHeavyLeft"; + return (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; } } 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") { MWBase::World *world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 196e7d8c7..6526b200f 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -507,7 +507,7 @@ namespace MWGui mScrollBar->setVisible(true); } - BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits().max()); + BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits::max()); for (std::vector::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) (*it)->write(typesetter, &mKeywordSearch, mTopicLinks); diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index c27737285..a0421ec28 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -3,43 +3,91 @@ 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") - , mMode(FadingMode_In) - , mRemainingTime(0.f) - , mTargetTime(0.f) - , mTargetAlpha(0.f) , mCurrentAlpha(0.f) - , mStartAlpha(0.f) , mFactor(1.f) + , mRepeat(false) { mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); - + setTexture(texturePath); setVisible(false); } + void ScreenFader::setTexture(const std::string & texturePath) + { + mMainWidget->setProperty("ImageTexture", texturePath); + } + void ScreenFader::update(float dt) { - if (mRemainingTime > 0) + if (!mQueue.empty()) { - if (mMode == FadingMode_In) - { - mCurrentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); - if (mCurrentAlpha < mTargetAlpha) mCurrentAlpha = mTargetAlpha; - } - else if (mMode == FadingMode_Out) - { - mCurrentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); - if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha; - } - - mRemainingTime -= dt; + if (!mQueue.front()->isRunning()) + mQueue.front()->start(); + mQueue.front()->update(dt); } - - if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f) - mMainWidget->setVisible(false); - else - applyAlpha(); } void ScreenFader::applyAlpha() @@ -50,62 +98,79 @@ namespace MWGui void ScreenFader::fadeIn(float time) { - if (time<0.f) return; - if (time==0.f) - { - mCurrentAlpha = 0.f; - applyAlpha(); - return; - } - - mStartAlpha = mCurrentAlpha; - mTargetAlpha = 0.f; - mMode = FadingMode_In; - mTargetTime = time; - mRemainingTime = time; + queue(time, 1.f); } void ScreenFader::fadeOut(const float time) { - if (time<0.f) return; - if (time==0.f) - { - mCurrentAlpha = 1.f; - applyAlpha(); - return; - } - - mStartAlpha = mCurrentAlpha; - mTargetAlpha = 1.f; - mMode = FadingMode_Out; - mTargetTime = time; - mRemainingTime = time; + queue(time, 0.f); } void ScreenFader::fadeTo(const int percent, const float time) { - if (time<0.f) return; - 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; + queue(time, percent/100.f); } void ScreenFader::setFactor(float 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; + } } diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index 975006a85..402554555 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -1,15 +1,44 @@ #ifndef OPENMW_MWGUI_SCREENFADER_H #define OPENMW_MWGUI_SCREENFADER_H +#include + +#include + #include "windowbase.hpp" namespace MWGui { + class ScreenFader; + + class FadeOp + { + public: + typedef boost::shared_ptr 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 { public: - ScreenFader(); + ScreenFader(const std::string & texturePath); + + void setTexture(const std::string & texturePath); void update(float dt); @@ -18,27 +47,25 @@ namespace MWGui void fadeTo(const int percent, const float time); 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: - enum FadingMode - { - FadingMode_In, - FadingMode_Out - }; - void applyAlpha(); - FadingMode mMode; - - float mRemainingTime; - float mTargetTime; - float mTargetAlpha; float mCurrentAlpha; - float mStartAlpha; - float mFactor; - }; + bool mRepeat; // repeat queued operations without removing them + std::deque mQueue; + }; } #endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 16295d3a5..5a1b0b417 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -120,6 +120,9 @@ namespace MWGui , mCompanionWindow(NULL) , mVideoBackground(NULL) , mVideoWidget(NULL) + , mWerewolfFader(NULL) + , mBlindnessFader(NULL) + , mHitFader(NULL) , mScreenFader(NULL) , mDebugWindow(NULL) , mTranslationDataStorage (translationDataStorage) @@ -127,6 +130,8 @@ namespace MWGui , mInputBlocker(NULL) , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) + , mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI")) + , mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI")) , mHudEnabled(true) , mGuiEnabled(true) , mCursorVisible(true) @@ -267,7 +272,17 @@ namespace MWGui mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); 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(); mInputBlocker = MyGUI::Gui::getInstance().createWidget("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); @@ -359,6 +374,8 @@ namespace MWGui delete mCursorManager; delete mRecharge; delete mCompanionWindow; + delete mHitFader; + delete mWerewolfFader; delete mScreenFader; delete mDebugWindow; @@ -862,6 +879,9 @@ namespace MWGui mConsole->checkReferenceAvailable(); mCompanionWindow->onFrame(); + mWerewolfFader->update(frameDuration); + mBlindnessFader->update(frameDuration); + mHitFader->update(frameDuration); mScreenFader->update(frameDuration); mDebugWindow->onFrame(frameDuration); @@ -1450,7 +1470,10 @@ namespace MWGui const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if (player.getClass().getNpcStats(player).isWerewolf()) + { + setWerewolfOverlay(true); forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); + } } // Remove this method for MyGUI 3.2.2 @@ -1544,6 +1567,8 @@ namespace MWGui mForceHidden = GW_None; + setWerewolfOverlay(false); + mGuiModes.clear(); MWBase::Environment::get().getInputManager()->changeInputMode(false); updateVisible(); @@ -1718,22 +1743,46 @@ namespace MWGui void WindowManager::fadeScreenIn(const float time) { - mScreenFader->fadeIn(time); + mScreenFader->clearQueue(); + mScreenFader->fadeOut(time); } void WindowManager::fadeScreenOut(const float time) { - mScreenFader->fadeOut(time); + mScreenFader->clearQueue(); + mScreenFader->fadeIn(time); } void WindowManager::fadeScreenTo(const int percent, const float time) { + mScreenFader->clearQueue(); 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) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index d473988f9..aa5bd0fc9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -330,8 +330,11 @@ namespace MWGui virtual void fadeScreenOut(const float time); /// Fade the screen to a specified percentage of black, over \a time seconds virtual void fadeScreenTo(const int percent, const float time); - /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. - virtual void setScreenFactor (float factor); + /// Darken the screen to a specified percentage + virtual void setBlindness(const int percent); + + virtual void activateHitOverlay(bool interrupt); + virtual void setWerewolfOverlay(bool set); virtual void toggleDebugWindow(); @@ -387,6 +390,9 @@ namespace MWGui CompanionWindow* mCompanionWindow; MyGUI::ImageBox* mVideoBackground; VideoWidget* mVideoWidget; + ScreenFader* mWerewolfFader; + ScreenFader* mBlindnessFader; + ScreenFader* mHitFader; ScreenFader* mScreenFader; DebugWindow* mDebugWindow; @@ -398,6 +404,8 @@ namespace MWGui bool mCrosshairEnabled; bool mSubtitlesEnabled; + bool mHitFaderEnabled; + bool mWerewolfOverlayEnabled; bool mHudEnabled; bool mGuiEnabled; bool mCursorVisible; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index da6aec0be..a31e64dd3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -220,7 +220,7 @@ namespace MWMechanics // 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().max(); + float gemCapacity = std::numeric_limits::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) @@ -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 int damageEffects[] = { ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison, @@ -612,11 +618,22 @@ namespace MWMechanics if (weather > 1) damageScale *= fMagicSunBlockedMult; health.setCurrent(health.getCurrent() - magnitude * duration * damageScale); + + if (magnitude * damageScale > 0.0f) + receivedMagicDamage = true; } else + { 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); if (!wasDead && creatureStats.isDead()) @@ -875,13 +892,13 @@ namespace MWMechanics static const float fSuffocationDamage = world->getStore().get().find("fSuffocationDamage")->getFloat(); 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()) - { - MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); - if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown")) - sndmgr->playSound("drown", 1.0f, 1.0f); - } + MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); } } else diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 152854af9..cc8279b1e 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -166,10 +166,18 @@ namespace MWMechanics { const CreatureStats& stats = actor.getClass().getCreatureStats(actor); - // Never casting racial spells (ST_Power and F_Always) - if (spell->mData.mType != ESM::Spell::ST_Spell || spell->mData.mFlags & ESM::Spell::F_Always) + if (spell->mData.mType != ESM::Spell::ST_Spell) 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()->mBase->mRace; + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(raceid); + if (race->mPowers.exists(spell->mId)) + return 0.f; + } + if (spell->mData.mCost > stats.getMagicka().getCurrent()) return 0.f; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 35432e979..d33bb6ad1 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -292,6 +292,7 @@ namespace MWMechanics , mTarget(target) , mStack(false) , mHitPosition(0,0,0) + , mAlwaysSucceed(false) { } @@ -761,7 +762,7 @@ namespace MWMechanics int school = 0; - if (mCaster.getClass().isActor()) + if (mCaster.getClass().isActor() && !mAlwaysSucceed) { school = getSpellSchool(spell, mCaster); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index c01fede37..395ae043b 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -68,6 +68,7 @@ namespace MWMechanics std::string mId; // ID of spell, potion, item etc std::string mSourceName; // Display name for spell, potion, etc Ogre::Vector3 mHitPosition; // Used for spawning area orb + bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false) public: CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 1630e4005..d9c953133 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -85,7 +85,7 @@ namespace MWRender mNode = renderRoot->createChildSceneNode(); 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(); mCamera->setPosition(mPosition * scale); @@ -118,7 +118,7 @@ namespace MWRender assert(mAnimation); delete mAnimation; 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; mCharacter.getClass().adjustScale(mCharacter, scale); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 9e93bd314..67be5916c 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -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), mVisibilityFlags(visibilityFlags), mListenerDisabled(disableListener), @@ -186,7 +186,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal) + mNpcType(Type_Normal), + mSoundsDisabled(disableSounds) { mNpc = mPtr.get()->mBase; @@ -297,7 +298,6 @@ void NpcAnimation::updateParts() { mAlpha = 1.f; const MWWorld::Class &cls = mPtr.getClass(); - MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); NpcType curType = Type_Normal; 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]); + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) { MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); @@ -625,6 +626,11 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartslots[type] = -1; 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) @@ -654,8 +660,22 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g removeIndividualPart(type); mPartslots[type] = group; mPartPriorities[type] = priority; - 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) { Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); @@ -760,7 +780,7 @@ void NpcAnimation::showWeapons(bool showWeapon) mShowWeapons = 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); if(weapon != inv.end()) { @@ -793,9 +813,8 @@ void NpcAnimation::showWeapons(bool showWeapon) void NpcAnimation::showCarriedLeft(bool 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); - if(show && iter != inv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*iter); @@ -928,4 +947,9 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce } } +void NpcAnimation::equipmentChanged() +{ + updateParts(); +} + } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 979210591..ee62fce9c 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -51,7 +51,7 @@ public: class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener { public: - virtual void equipmentChanged() { updateParts(); } + virtual void equipmentChanged(); virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); public: @@ -70,6 +70,7 @@ private: // Bounded Parts NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count]; + std::string mSoundIds[ESM::PRT_Count]; const ESM::NPC *mNpc; std::string mHeadModel; @@ -97,6 +98,7 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; + bool mSoundsDisabled; void updateNpcBase(); @@ -123,10 +125,11 @@ public: * 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. * Those need to be manually rendered anyway. + * @param disableSounds Same as \a disableListener but for playing items sounds * @param viewMode */ 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 void enableHeadAnimation(bool enable); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b1e2240ba..ed25e70a6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -36,6 +36,7 @@ #include "../mwbase/statemanager.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" #include "../mwworld/ptr.hpp" @@ -346,9 +347,12 @@ void RenderingManager::update (float duration, bool paused) MWWorld::Ptr player = world->getPlayerPtr(); 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(); + if (player.getClass().getNpcStats(player).isWerewolf()) + MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mCamera->isFirstPerson()); + // player position MWWorld::RefData &data = player.getRefData(); Ogre::Vector3 playerPos(data.getPosition().pos); @@ -511,7 +515,7 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue if (density == 0) { mFogStart = 0; - mFogEnd = std::numeric_limits().max(); + mFogEnd = std::numeric_limits::max(); mRendering.getCamera()->setFarClipDistance (max); } else diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 94d734029..a568b7943 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -153,7 +153,7 @@ namespace MWScript if (cell->getCell()->hasWater()) runtime.push (cell->getWaterLevel()); else - runtime.push (-std::numeric_limits().max()); + runtime.push (-std::numeric_limits::max()); } }; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index c43a010b4..cb02a6c97 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -438,7 +438,7 @@ namespace MWScript // 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) - return std::numeric_limits().max(); + return std::numeric_limits::max(); double diff[3]; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index ef879a95a..0de8f3b91 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -854,6 +854,7 @@ namespace MWScript MWMechanics::CastSpell cast(ptr, target); cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); + cast.mAlwaysSucceed = true; cast.cast(spell); } }; @@ -871,6 +872,7 @@ namespace MWScript MWMechanics::CastSpell cast(ptr, ptr); cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos); + cast.mAlwaysSucceed = true; cast.cast(spell); } }; diff --git a/apps/openmw/mwsound/loudness.cpp b/apps/openmw/mwsound/loudness.cpp index ebe3bf1ec..c64913b1f 100644 --- a/apps/openmw/mwsound/loudness.cpp +++ b/apps/openmw/mwsound/loudness.cpp @@ -29,7 +29,7 @@ namespace MWSound else if (type == SampleType_Int16) { value = *reinterpret_cast(&data[sample*advance]); - value /= float(std::numeric_limits().max()); + value /= float(std::numeric_limits::max()); } else if (type == SampleType_Float32) { diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 812e49a64..781bfb5d5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -454,6 +454,7 @@ namespace MWSound while(snditer != mActiveSounds.end()) { if(snditer->second.first != MWWorld::Ptr() && + snditer->second.first.getCellRef().getRefId() != "player" && snditer->second.first.getCell() == cell) { snditer->first->stop(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index ea1c8827a..16c2469c1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -429,4 +429,9 @@ namespace MWWorld return getEncumbrance(ptr) / capacity; } + + std::string Class::getSound(const MWWorld::Ptr&) const + { + return std::string(); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 5f266b45c..b66ca7488 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -339,6 +339,9 @@ namespace MWWorld virtual void respawn (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; }; } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index ecc679013..9032b04e1 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -148,16 +148,18 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); fireEquipmentChangedEvent(); + updateMagicEffects(actor); } void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) { - // Only *one* change event should be fired mUpdatesEnabled = false; for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) unequipSlot(slot, actor); + mUpdatesEnabled = true; + fireEquipmentChangedEvent(); updateMagicEffects(actor); } @@ -204,8 +206,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && (actor.getClass().getScript(actor).empty() || !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) + { continue; - + } int testSkill = test.getClass().getEquipmentSkill (test); std::pair, bool> itemsSlots = @@ -277,11 +280,13 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) bool changed = false; for (std::size_t i=0; i= 1.0f/60.0f) { + // Collision events should be available on every frame + mCollisions.clear(); + mStandingCollisions.clear(); + const MWBase::World *world = MWBase::Environment::get().getWorld(); PtrVelocityList::iterator iter = mMovementQueue.begin(); for(;iter != mMovementQueue.end();++iter) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 66c9f5b71..6f18a6ef3 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -124,10 +124,10 @@ namespace MWWorld void Scene::getGridCenter(int &cellX, int &cellY) { - int maxX = std::numeric_limits().min(); - int maxY = std::numeric_limits().min(); - int minX = std::numeric_limits().max(); - int minY = std::numeric_limits().max(); + int maxX = std::numeric_limits::min(); + int maxY = std::numeric_limits::min(); + int minX = std::numeric_limits::max(); + int minY = std::numeric_limits::max(); CellStoreCollection::iterator iter = mActiveCells.begin(); while (iter!=mActiveCells.end()) { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index dd6e7d7fc..383641d2d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2078,6 +2078,9 @@ namespace MWWorld void World::hurtStandingActors(const Ptr &object, float healthPerSecond) { + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + return; + std::vector actors; mPhysics->getActorsStandingOn(object, actors); for (std::vector::iterator it = actors.begin(); it != actors.end(); ++it) @@ -2087,14 +2090,28 @@ namespace MWWorld continue; MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); + if (stats.isDead()) + continue; MWMechanics::DynamicStat health = stats.getHealth(); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); 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) { + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + return; + std::vector actors; mPhysics->getActorsCollidingWith(object, actors); for (std::vector::iterator it = actors.begin(); it != actors.end(); ++it) @@ -2104,9 +2121,20 @@ namespace MWWorld continue; MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); + if (stats.isDead()) + continue; MWMechanics::DynamicStat health = stats.getHealth(); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); 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->setWerewolfOverlay(werewolf); + // Witnesses of the player's transformation will make them a globally known werewolf std::vector closeActors; 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) { + if (ptr.getRefData().getHandle() == "player" && Settings::Manager::getBool("hit fader", "GUI")) + return; + int type = ptr.getClass().getBloodTexture(ptr); std::string texture; switch (type) diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index c4152533e..3c76cc3b4 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -34,8 +34,8 @@ namespace ESMTerrain if (!land) return false; - min = std::numeric_limits().max(); - max = -std::numeric_limits().max(); + min = std::numeric_limits::max(); + max = -std::numeric_limits::max(); for (int row=0; row().min()), - mMaxValue(std::numeric_limits().max()) + : mValue(0), mMinValue(std::numeric_limits::min()), + mMaxValue(std::numeric_limits::max()) {} void initialiseOverride(); diff --git a/credits.txt b/credits.txt index ab83b93be..225bba194 100644 --- a/credits.txt +++ b/credits.txt @@ -94,6 +94,7 @@ Thomas Luppi (Digmaster) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) Vincent Heuken +vocollapse Packagers: Alexander Olofsson (Ace) - Windows diff --git a/docs/Doxyfile b/docs/Doxyfile.cmake similarity index 99% rename from docs/Doxyfile rename to docs/Doxyfile.cmake index a74fc7b0a..38ad84165 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile.cmake @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # 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- # directories (in 2 levels) under the output directory of each output format and @@ -764,10 +764,10 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = apps \ - components \ - libs \ - docs +INPUT = @OpenMW_SOURCE_DIR@/apps \ + @OpenMW_SOURCE_DIR@/components \ + @OpenMW_SOURCE_DIR@/libs \ + @OpenMW_BINARY_DIR@/docs/mainpage.hpp # 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 diff --git a/docs/DoxyfilePages b/docs/DoxyfilePages.cmake similarity index 99% rename from docs/DoxyfilePages rename to docs/DoxyfilePages.cmake index dca9d7a12..d50a043d6 100644 --- a/docs/DoxyfilePages +++ b/docs/DoxyfilePages.cmake @@ -38,7 +38,7 @@ PROJECT_NUMBER = # 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. -OUTPUT_DIRECTORY = ../doxygen +OUTPUT_DIRECTORY = @DOXYGEN_PAGES_OUTPUT_DIR@ # 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 @@ -573,10 +573,10 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = apps \ - components \ - libs \ - docs +INPUT = @OpenMW_SOURCE_DIR@/apps \ + @OpenMW_SOURCE_DIR@/components \ + @OpenMW_SOURCE_DIR@/libs \ + @OpenMW_BINARY_DIR@/docs/mainpage.hpp # 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 diff --git a/extern/sdl4ogre/sdlwindowhelper.cpp b/extern/sdl4ogre/sdlwindowhelper.cpp index e040b8868..44993947f 100644 --- a/extern/sdl4ogre/sdlwindowhelper.cpp +++ b/extern/sdl4ogre/sdlwindowhelper.cpp @@ -27,7 +27,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, throw std::runtime_error("Couldn't get WM Info!"); Ogre::String winHandle; - Ogre::String winHandleSurface; switch (wmInfo.subsystem) { @@ -46,8 +45,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, #elif ANDROID case SDL_SYSWM_ANDROID: winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window); - winHandleSurface = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.surface); - break; #else 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. #ifdef ANDROID - params.insert(std::make_pair("externalSurface", winHandleSurface)); + SDL_GLContext context= SDL_GL_CreateContext(window); + params.insert(std::make_pair("currentGLContext","True")); #endif params.insert(std::make_pair("externalWindowHandle", winHandle)); diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 06d999189..12b52d3db 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -41,6 +41,9 @@ tooltip delay = 0 subtitles = false +hit fader = true +werewolf overlay = true + [General] # Camera field of view field of view = 55