diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 59cad6a66..94f641edc 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -175,6 +175,12 @@ namespace CSMWorld { mContainer[index].setModified(record); } + else + { + // Overwrite + mContainer[index].setModified(record); + mContainer[index].merge(); + } } return index; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 335c0453a..689419f44 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -173,6 +173,16 @@ namespace MWClass return info; } + bool Light::showsInInventory (const MWWorld::ConstPtr& ptr) const + { + const ESM::Light* light = ptr.get()->mBase; + + if (!(light->mData.mFlags & ESM::Light::Carry)) + return false; + + return Class::showsInInventory(ptr); + } + boost::shared_ptr Light::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 5ec21f41f..68fd2d2c7 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -26,6 +26,8 @@ namespace MWClass virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual bool showsInInventory (const MWWorld::ConstPtr& ptr) const; + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; ///< Generate action for activation diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index b80850ba1..061c8c4c4 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -77,10 +77,8 @@ void InventoryItemModel::update() for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { MWWorld::Ptr item = *it; - // NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken. - // Vanilla likely uses a hack like this since there's no other way to prevent it from - // being shown or taken. - if(item.getCellRef().getRefId() == "werewolfrobe") + + if (!item.getClass().showsInInventory(item)) continue; ItemStack newItem (item, this, item.getRefData().getCount()); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index bd864b45b..21b90991c 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -545,10 +545,7 @@ namespace MWGui if(invStore.getSlot(slot) != invStore.end()) { MWWorld::Ptr item = *invStore.getSlot(slot); - // NOTE: Don't allow users to select WerewolfRobe objects in the inventory. Vanilla - // likely uses a hack like this since there's no other way to prevent it from being - // taken. - if(item.getCellRef().getRefId() == "werewolfrobe") + if (!item.getClass().showsInInventory(item)) return MWWorld::Ptr(); return item; } diff --git a/apps/openmw/mwgui/tradeitemmodel.cpp b/apps/openmw/mwgui/tradeitemmodel.cpp index a5a2b3e88..ae3feb61c 100644 --- a/apps/openmw/mwgui/tradeitemmodel.cpp +++ b/apps/openmw/mwgui/tradeitemmodel.cpp @@ -163,6 +163,10 @@ namespace MWGui MWWorld::Ptr base = item.mBase; if(Misc::StringUtils::ciEqual(base.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) continue; + + if (!base.getClass().showsInInventory(base)) + return; + if(!base.getClass().canSell(base, services)) continue; diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 68bcae695..6727be51b 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -362,9 +362,9 @@ namespace MWMechanics } } - // Original engine behavior seems to be to back up during ranged combat - // according to fCombatDistance or opponent's weapon range, unless opponent - // is also using a ranged weapon + // Below behavior for backing up during ranged combat differs from vanilla. + // Vanilla is observed as backing up only as far as fCombatDistance or + // opponent's weapon range, or not backing up if opponent is also using a ranged weapon if (isDistantCombat && distToTarget < rangeAttack / 4) { mMovement.mPosition[1] = -1; @@ -468,6 +468,8 @@ std::string chooseBestAttack(const ESM::Weapon* weapon) else attackType = "chop"; } + else + MWMechanics::CharacterController::setAttackTypeRandomly(attackType); return attackType; } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index d993b1301..4b197d273 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1312,9 +1312,9 @@ bool CharacterController::updateWeaponState() mAttackType = "shoot"; else { - if (isWeapon) + if(mPtr == getPlayer()) { - if(mPtr == getPlayer()) + if (isWeapon) { if (Settings::Manager::getBool("best attack", "Game")) { @@ -1324,10 +1324,10 @@ bool CharacterController::updateWeaponState() else setAttackTypeBasedOnMovement(); } - // else if (mPtr != getPlayer()) use mAttackType already set by AiCombat + else + setAttackTypeRandomly(mAttackType); } - else - setAttackTypeRandomly(); + // else if (mPtr != getPlayer()) use mAttackType set by AiCombat } mAnimation->play(mCurrentWeapon, priorityWeapon, @@ -2188,17 +2188,6 @@ void CharacterController::updateMagicEffects() mAnimation->setLightEffect(light); } -void CharacterController::setAttackTypeRandomly() -{ - float random = Misc::Rng::rollProbability(); - if (random >= 2/3.f) - mAttackType = "thrust"; - else if (random >= 1/3.f) - mAttackType = "slash"; - else - mAttackType = "chop"; -} - void CharacterController::setAttackTypeBasedOnMovement() { float *move = mPtr.getClass().getMovementSettings(mPtr).mPosition; @@ -2240,6 +2229,17 @@ void CharacterController::setAIAttackType(std::string attackType) mAttackType = attackType; } +void CharacterController::setAttackTypeRandomly(std::string& attackType) +{ + float random = Misc::Rng::rollProbability(); + if (random >= 2/3.f) + attackType = "thrust"; + else if (random >= 1/3.f) + attackType = "slash"; + else + attackType = "chop"; +} + bool CharacterController::readyToPrepareAttack() const { return (mHitState == CharState_None || mHitState == CharState_Block) diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index deaf63539..3a84f0f78 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -198,7 +198,6 @@ class CharacterController : public MWRender::Animation::TextKeyListener bool mAttackingOrSpell; void setAttackTypeBasedOnMovement(); - void setAttackTypeRandomly(); void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false); void refreshHitRecoilAnims(); @@ -270,6 +269,7 @@ public: void setAttackingOrSpell(bool attackingOrSpell); void setAIAttackType(std::string attackType); // set and used by AiCombat + static void setAttackTypeRandomly(std::string& attackType); bool readyToPrepareAttack() const; bool readyToStartAttack() const; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 3725065b7..d04252a2c 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -277,6 +277,14 @@ namespace MWWorld throw std::runtime_error ("class does not have a tool tip"); } + bool Class::showsInInventory (const ConstPtr& ptr) const + { + // NOTE: Don't show WerewolfRobe objects in the inventory, or allow them to be taken. + // Vanilla likely uses a hack like this since there's no other way to prevent it from + // being shown or taken. + return (ptr.getCellRef().getRefId() != "werewolfrobe"); + } + bool Class::hasToolTip (const ConstPtr& ptr) const { return false; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 8a8e0191e..8d3f9b891 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -98,6 +98,11 @@ namespace MWWorld virtual MWGui::ToolTipInfo getToolTipInfo (const ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + virtual bool showsInInventory (const ConstPtr& ptr) const; + ///< Return whether ptr shows in inventory views. + /// Hidden items are not displayed and cannot be (re)moved by the user. + /// \return True if shown, false if hidden. + virtual MWMechanics::NpcStats& getNpcStats (const Ptr& ptr) const; ///< Return NPC stats or throw an exception, if class does not have NPC stats /// (default implementation: throw an exception)