From 900bc06d2c236b80fe6c422ba335aefb897b37a7 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 20 Dec 2013 22:38:23 +0100 Subject: [PATCH] Fixes #845: NPCs hold torches during the day Moved 'equipping torches at night and unequipping at day' code from Character to Actors class. Removed unneeded showLights method (introduced in previous commits) from animation/npcanimation classes. Since this commit autoEquip() method doesn't automatically equip lights. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwmechanics/actors.cpp | 37 ++++++++++++++++++- apps/openmw/mwmechanics/actors.hpp | 11 +++--- apps/openmw/mwmechanics/character.cpp | 51 +++++--------------------- apps/openmw/mwrender/animation.hpp | 1 - apps/openmw/mwrender/npcanimation.cpp | 34 +++++------------ apps/openmw/mwrender/npcanimation.hpp | 2 - apps/openmw/mwworld/inventorystore.cpp | 7 ++++ 7 files changed, 66 insertions(+), 77 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 22a641b34b..1561c9d5b4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -439,15 +439,48 @@ namespace MWMechanics void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) { - //If holding a light... + bool isPlayer = ptr.getRefData().getHandle()=="player"; + MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr); MWWorld::ContainerStoreIterator heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + /** + * Automatically equip NPCs torches at night and unequip them at day + */ + if (!isPlayer && !MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile()) + { + if (mTorchPtr.isEmpty()) + { + mTorchPtr = inventoryStore.search("torch_infinite_time"); + } + if (MWBase::Environment::get().getWorld()->isNight()) + { + if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) + { + inventoryStore.unequipItem(*heldIter, ptr); + } + else if (heldIter == inventoryStore.end() && !mTorchPtr.isEmpty()) + { + heldIter = inventoryStore.add(mTorchPtr, ptr); + inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, heldIter, ptr); + } + } + else + { + if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name()) + { + inventoryStore.unequipItem(*heldIter, ptr); + inventoryStore.add(*heldIter, ptr); + inventoryStore.autoEquip(ptr); + } + } + } + + //If holding a light... if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) { // Use time from the player's light - bool isPlayer = ptr.getRefData().getHandle()=="player"; if(isPlayer) { float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 6afdefdbdc..411ac54ca8 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -25,14 +25,13 @@ namespace MWMechanics { class Actors { - typedef std::map PtrControllerMap; - PtrControllerMap mActors; - - std::map mDeathCount; - - void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused); + typedef std::map PtrControllerMap; + PtrControllerMap mActors; + std::map mDeathCount; + MWWorld::Ptr mTorchPtr; + void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused); void adjustMagicEffects (const MWWorld::Ptr& creature); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index f2b3532974..e3373e7f3c 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -709,50 +709,17 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun } } - if (mPtr.getRefData().getHandle() != "player") + MWWorld::ContainerStoreIterator item = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + if (item != inv.end() && item->getTypeName() == typeid(ESM::Light).name()) { - if (MWBase::Environment::get().getWorld()->isNight()) - { - MWWorld::ContainerStoreIterator item = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if (item != inv.end() && item->getTypeName() != typeid(ESM::Light).name()) - { - inv.unequipItem(*item, mPtr); - } - else if (item == inv.end()) - { - MWWorld::Ptr itemPtr = inv.search("torch_infinite_time"); - if (!itemPtr.isEmpty()) - { - item = inv.add(itemPtr, mPtr); - inv.equip(MWWorld::InventoryStore::Slot_CarriedLeft, item, mPtr); - } - } - - if (item != inv.end() && item->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)); - } - } - } - else - { - if (mAnimation->isPlaying("torch")) - { - mAnimation->disable("torch"); - mAnimation->showLights(false); - MWWorld::ContainerStoreIterator item = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if (item != inv.end() && item->getTypeName() == typeid(ESM::Light).name()) - { - inv.unequipItem(*item, mPtr); - inv.add(*item, mPtr); - } - } - } + 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"); + } + return forcestateupdate; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 16af6d5a67..aa04e39e21 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -275,7 +275,6 @@ 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 2da45e8a19..eb0c5dfbc8 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -118,7 +118,6 @@ 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) { @@ -321,7 +320,6 @@ 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; @@ -662,12 +660,21 @@ void NpcAnimation::showShield(bool 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()) + 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()) { 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 { @@ -675,27 +682,6 @@ void NpcAnimation::showShield(bool show) } } -void NpcAnimation::showLights(bool show) -{ - MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator light = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - - if(show && light != inv.end() && light->getTypeName() == typeid(ESM::Light).name()) - { - mShowLights = show; - Ogre::Vector3 glowColor = getEnchantmentColor(*light); - std::string mesh = MWWorld::Class::get(*light).getModel(*light); - addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, - mesh, !light->getClass().getEnchantment(*light).empty(), &glowColor); - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], light->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 0500b46c61..04dde87c7f 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -54,7 +54,6 @@ private: ViewMode mViewMode; bool mShowWeapons; bool mShowShield; - bool mShowLights; int mVisibilityFlags; @@ -102,7 +101,6 @@ 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/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 57e35adce9..856697b8e4 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -175,6 +175,13 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { Ptr test = *iter; + + // Don't autoEquip lights + if (test.getTypeName() == typeid(ESM::Light).name()) + { + continue; + } + int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test); std::pair, bool> itemsSlots =