From 79a440e94aa32965b057ab24b4d980bccd0937e4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 30 Dec 2013 17:53:02 +0100 Subject: [PATCH] Many additions to 900bc06d2c236b: - Fix indentation - Consider any kind of light, not just torch_infinite_time - Hostile NPCs should also wear lights, if they have nothing else that could use the slot (or a twohanded weapon) - Remove redundant code and don't add additional lights to the inventory - World::isDark returns false for interiors which are unaffected by weather --- apps/openmw/mwbase/world.hpp | 3 +- apps/openmw/mwmechanics/actors.cpp | 65 +++++++++++++++++--------- apps/openmw/mwmechanics/actors.hpp | 1 - apps/openmw/mwmechanics/character.cpp | 8 ++-- apps/openmw/mwworld/inventorystore.cpp | 2 +- apps/openmw/mwworld/weather.cpp | 6 ++- apps/openmw/mwworld/weather.hpp | 3 +- apps/openmw/mwworld/worldimp.cpp | 4 +- apps/openmw/mwworld/worldimp.hpp | 3 +- 9 files changed, 59 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 48803a2d8..609f873ee 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -428,7 +428,8 @@ namespace MWBase virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0; - virtual bool isNight() const = 0; + // Are we in an exterior or pseudo-exterior cell and it's night? + virtual bool isDark() const = 0; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1aa9ce9f5..62242ee8c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -448,36 +448,57 @@ namespace MWMechanics /** * Automatically equip NPCs torches at night and unequip them at day */ - if (!isPlayer && !MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile()) + if (!isPlayer) { - if (mTorchPtr.isEmpty()) - { - mTorchPtr = inventoryStore.search("torch_infinite_time"); - } + MWWorld::ContainerStoreIterator torch = inventoryStore.end(); + for (MWWorld::ContainerStoreIterator it = inventoryStore.begin(); it != inventoryStore.end(); ++it) + { + if (it->getTypeName() == typeid(ESM::Light).name()) + { + torch = it; + break; + } + } - if (MWBase::Environment::get().getWorld()->isNight()) - { - if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) + if (MWBase::Environment::get().getWorld()->isDark()) { - inventoryStore.unequipItem(*heldIter, ptr); + if (torch != inventoryStore.end()) + { + if (!MWWorld::Class::get (ptr).getCreatureStats (ptr).isHostile()) + { + // For non-hostile NPCs, unequip whatever is in the left slot in favor of a light. + if (heldIter != inventoryStore.end() && heldIter->getTypeName() != typeid(ESM::Light).name()) + inventoryStore.unequipItem(*heldIter, ptr); + + // Also unequip twohanded weapons which conflict with anything in CarriedLeft + if (torch->getClass().canBeEquipped(*torch, ptr).first == 3) + inventoryStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, ptr); + } + + heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + + // If we have a torch and can equip it (left slot free, no + // twohanded weapon in right slot), then equip it now. + if (heldIter == inventoryStore.end() + && torch->getClass().canBeEquipped(*torch, ptr).first == 1) + { + inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torch, ptr); + } + } } - else if (heldIter == inventoryStore.end() && !mTorchPtr.isEmpty()) + else { - heldIter = inventoryStore.add(mTorchPtr, ptr); - inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, heldIter, ptr); + if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name()) + { + // At day, unequip lights and auto equip shields or other suitable items + // (Note: autoEquip will ignore lights) + inventoryStore.autoEquip(ptr); + } } - } - else - { - if (heldIter != inventoryStore.end() && heldIter->getTypeName() == typeid(ESM::Light).name()) - { - inventoryStore.unequipItem(*heldIter, ptr); - inventoryStore.add(*heldIter, ptr); - inventoryStore.autoEquip(ptr); - } - } } + heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + //If holding a light... if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) { diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 411ac54ca..b03b68e89 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -29,7 +29,6 @@ namespace MWMechanics PtrControllerMap mActors; std::map mDeathCount; - MWWorld::Ptr mTorchPtr; void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 17eff3d02..351e33f13 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -36,8 +36,6 @@ #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" -#include "../mwworld/actionequip.hpp" -#include "../mwworld/actiontake.hpp" namespace { @@ -724,12 +722,12 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun && mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand) { - 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->disable("torch"); } return forcestateupdate; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 849e9ff26..2c7c05317 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -179,7 +179,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) // Don't autoEquip lights if (test.getTypeName() == typeid(ESM::Light).name()) { - continue; + continue; } int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test); diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index c355d86a8..5967a02fd 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -708,7 +708,9 @@ float WeatherManager::getWindSpeed() const return mWindSpeed; } -bool WeatherManager::isNight() const +bool WeatherManager::isDark() const { - return (mHour < mSunriseTime || mHour > mNightStart - 1); + bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior() + || MWBase::Environment::get().getWorld()->isCellQuasiExterior()); + return exterior && (mHour < mSunriseTime || mHour > mNightStart - 1); } diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 4c412c449..5e8d059ee 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -152,7 +152,8 @@ namespace MWWorld void modRegion(const std::string ®ionid, const std::vector &chances); - bool isNight() const; + /// @see World::isDark + bool isDark() const; private: float mHour; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index cf32217b6..82029d11d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2286,8 +2286,8 @@ namespace MWWorld actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility); } - bool World::isNight() const + bool World::isDark() const { - return mWeatherManager->isNight(); + return mWeatherManager->isDark(); } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 2c2f096ee..a7948dcf2 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -516,7 +516,8 @@ namespace MWWorld const MWWorld::Ptr& actor, const std::string& sourceName); virtual void breakInvisibility (const MWWorld::Ptr& actor); - virtual bool isNight() const; + // Are we in an exterior or pseudo-exterior cell and it's night? + virtual bool isDark() const; }; }