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 22a641b34..1561c9d5b 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 6afdefdbd..411ac54ca 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 f2b353297..e3373e7f3 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 16af6d5a6..aa04e39e2 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 2da45e8a1..eb0c5dfbc 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 0500b46c6..04dde87c7 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 57e35adce..856697b8e 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 =