From 91a4d9a2ebf1655cd41eaba48afc6c11de07723d Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Tue, 10 Dec 2013 23:48:49 +0100 Subject: [PATCH] Fixes #845: NPCs hold torches during the day Added method in WeatherManger and World which returns true if it is night. This method is used later in character controller to show torches (or other sources of light) at night and hide them at day. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwbase/world.hpp | 2 ++ apps/openmw/mwmechanics/character.cpp | 27 +++++++++++++++------ apps/openmw/mwrender/animation.hpp | 1 + apps/openmw/mwrender/npcanimation.cpp | 34 +++++++++++++++++++-------- apps/openmw/mwrender/npcanimation.hpp | 2 ++ apps/openmw/mwworld/weather.cpp | 5 ++++ apps/openmw/mwworld/weather.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 5 ++++ apps/openmw/mwworld/worldimp.hpp | 1 + 9 files changed, 62 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 8141af712..ae1497a08 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -421,6 +421,8 @@ namespace MWBase const MWWorld::Ptr& actor, const std::string& sourceName) = 0; virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0; + + virtual bool isNight() const = 0; }; } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index da3ed2523..4f7754951 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -707,17 +707,30 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun } } - - MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name()) + if (MWBase::Environment::get().getWorld()->isNight()) { + MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name()) + { + mAnimation->showLights(true); if(!mAnimation->isPlaying("torch")) - mAnimation->play("torch", Priority_Torch, - MWRender::Animation::Group_LeftArm, false, - 1.0f, "start", "stop", 0.0f, (~(size_t)0)); + mAnimation->play("torch", Priority_Torch, + MWRender::Animation::Group_LeftArm, false, + 1.0f, "start", "stop", 0.0f, (~(size_t)0)); + } + else if (mAnimation->isPlaying("torch")) + { + mAnimation->disable("torch"); + mAnimation->showLights(false); + mAnimation->showShield(true); + } } - else if(mAnimation->isPlaying("torch")) + else + { mAnimation->disable("torch"); + mAnimation->showLights(false); + mAnimation->showShield(true); + } return forcestateupdate; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index aa04e39e2..16af6d5a6 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -275,6 +275,7 @@ public: virtual void showWeapons(bool showWeapon); virtual void showShield(bool show) {} + virtual void showLights(bool show) {} void enableLights(bool enable); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index eb0c5dfbc..6e363ab88 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -118,6 +118,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mViewMode(viewMode), mShowWeapons(false), mShowShield(true), + mShowLights(false), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f) { @@ -320,6 +321,7 @@ void NpcAnimation::updateParts() showWeapons(mShowWeapons); showShield(mShowShield); + showLights(mShowLights); // Remember body parts so we only have to search through the store once for each race/gender/viewmode combination static std::map< std::pair,std::vector > sRaceMapping; @@ -660,21 +662,12 @@ void NpcAnimation::showShield(bool show) MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if (shield != inv.end() && shield->getTypeName() == typeid(ESM::Light).name()) - { - // ... Except for lights, which are still shown during spellcasting since they - // have their own (one-handed) casting animations - show = true; - } - if(show && shield != inv.end()) + if(show && shield != inv.end() && shield->getTypeName() != typeid(ESM::Light).name()) { Ogre::Vector3 glowColor = getEnchantmentColor(*shield); std::string mesh = MWWorld::Class::get(*shield).getModel(*shield); addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, mesh, !shield->getClass().getEnchantment(*shield).empty(), &glowColor); - - if (shield->getTypeName() == typeid(ESM::Light).name()) - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], shield->get()->mBase); } else { @@ -682,6 +675,27 @@ void NpcAnimation::showShield(bool show) } } +void NpcAnimation::showLights(bool show) +{ + mShowLights = show; + MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + + if(show && shield != inv.end() && shield->getTypeName() == typeid(ESM::Light).name()) + { + Ogre::Vector3 glowColor = getEnchantmentColor(*shield); + std::string mesh = MWWorld::Class::get(*shield).getModel(*shield); + addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, + mesh, !shield->getClass().getEnchantment(*shield).empty(), &glowColor); + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], shield->get()->mBase); + } + else + { + removeIndividualPart(ESM::PRT_Shield); + } +} + + void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound) { // During first auto equip, we don't play any sounds. diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 04dde87c7..0500b46c6 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -54,6 +54,7 @@ private: ViewMode mViewMode; bool mShowWeapons; bool mShowShield; + bool mShowLights; int mVisibilityFlags; @@ -101,6 +102,7 @@ public: virtual void showWeapons(bool showWeapon); virtual void showShield(bool showShield); + virtual void showLights(bool showLights); void setViewMode(ViewMode viewMode); diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 8b05d2256..c355d86a8 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -707,3 +707,8 @@ float WeatherManager::getWindSpeed() const { return mWindSpeed; } + +bool WeatherManager::isNight() const +{ + return (mHour < mSunriseTime || mHour > mNightStart - 1); +} diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 80cbe0418..4c412c449 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -152,6 +152,8 @@ namespace MWWorld void modRegion(const std::string ®ionid, const std::vector &chances); + bool isNight() const; + private: float mHour; int mDay, mMonth; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f64d22122..479feab3e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2244,4 +2244,9 @@ namespace MWWorld actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility); actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility); } + + bool World::isNight() const + { + return mWeatherManager->isNight(); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index c8133441d..2f8994c8e 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -506,6 +506,7 @@ namespace MWWorld const MWWorld::Ptr& actor, const std::string& sourceName); virtual void breakInvisibility (const MWWorld::Ptr& actor); + virtual bool isNight() const; }; }