From aa392ebf20ca6caab76cd250d4aa646593cf2097 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 26 Jan 2018 00:45:39 +0200 Subject: [PATCH] [Client] Unequip items if necessary when attr/skill modifier is set to 0 --- apps/openmw/mwmp/GUIController.cpp | 9 +++++ apps/openmw/mwmp/GUIController.hpp | 3 ++ apps/openmw/mwmp/LocalPlayer.cpp | 54 +++++++++++++++++++--------- apps/openmw/mwmp/MechanicsHelper.cpp | 35 ++++++++++++++++++ apps/openmw/mwmp/MechanicsHelper.hpp | 2 ++ 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmp/GUIController.cpp b/apps/openmw/mwmp/GUIController.cpp index c601221ec..a1ca5f999 100644 --- a/apps/openmw/mwmp/GUIController.cpp +++ b/apps/openmw/mwmp/GUIController.cpp @@ -59,6 +59,15 @@ void mwmp::GUIController::cleanUp() mChat = nullptr; } +void mwmp::GUIController::refreshGuiMode(MWGui::GuiMode guiMode) +{ + if (MWBase::Environment::get().getWindowManager()->containsMode(guiMode)) + { + MWBase::Environment::get().getWindowManager()->removeGuiMode(guiMode); + MWBase::Environment::get().getWindowManager()->pushGuiMode(guiMode); + } +} + void mwmp::GUIController::setupChat(const Settings::Manager &mgr) { assert(mChat == nullptr); diff --git a/apps/openmw/mwmp/GUIController.hpp b/apps/openmw/mwmp/GUIController.hpp index db42d692f..7ed57bcf6 100644 --- a/apps/openmw/mwmp/GUIController.hpp +++ b/apps/openmw/mwmp/GUIController.hpp @@ -35,6 +35,9 @@ namespace mwmp GUIController(); ~GUIController(); void cleanUp(); + + void refreshGuiMode(MWGui::GuiMode guiMode); + void setupChat(const Settings::Manager &manager); void printChatMessage(std::string &msg); diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 7db9b2338..02de21c5a 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -35,6 +35,7 @@ #include "Main.hpp" #include "Networking.hpp" #include "CellController.hpp" +#include "GUIController.hpp" #include "MechanicsHelper.hpp" using namespace mwmp; @@ -442,6 +443,7 @@ void LocalPlayer::updateEquipment(bool forceUpdate) { auto &item = equipedItems[slot]; MWWorld::ContainerStoreIterator it = invStore.getSlot(slot); + if (it != invStore.end()) { if (!::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipedItems[slot].refId)) @@ -796,47 +798,67 @@ void LocalPlayer::setDynamicStats() void LocalPlayer::setAttributes() { - MWBase::World *world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr ptrPlayer = world->getPlayerPtr(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWMechanics::CreatureStats *ptrCreatureStats = &ptrPlayer.getClass().getCreatureStats(ptrPlayer); MWMechanics::AttributeValue attributeValue; - for (int i = 0; i < 8; ++i) + for (int attributeIndex = 0; attributeIndex < 8; ++attributeIndex) { // If the server wants to clear our attribute's non-zero modifier, we need to remove // the spell effect causing it, to avoid an infinite loop where the effect keeps resetting // the modifier - if (creatureStats.mAttributes[i].mMod == 0 && ptrCreatureStats->getAttribute(i).getModifier() > 0) - ptrCreatureStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifyAttribute, i); + if (creatureStats.mAttributes[attributeIndex].mMod == 0 && ptrCreatureStats->getAttribute(attributeIndex).getModifier() > 0) + { + ptrCreatureStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifyAttribute, attributeIndex); + MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(ptrPlayer); + + // Is the modifier for this attribute still higher than 0? If so, unequip items that + // fortify the attribute + if (ptrCreatureStats->getAttribute(attributeIndex).getModifier() > 0) + { + MechanicsHelper::unequipItemsByEffect(ptrPlayer, ESM::MagicEffect::FortifyAttribute, attributeIndex, -1); + mwmp::Main::get().getGUIController()->refreshGuiMode(MWGui::GM_Inventory); + } + } - attributeValue.readState(creatureStats.mAttributes[i]); - ptrCreatureStats->setAttribute(i, attributeValue); + attributeValue.readState(creatureStats.mAttributes[attributeIndex]); + ptrCreatureStats->setAttribute(attributeIndex, attributeValue); } } void LocalPlayer::setSkills() { - MWBase::World *world = MWBase::Environment::get().getWorld(); - MWWorld::Ptr ptrPlayer = world->getPlayerPtr(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWMechanics::NpcStats *ptrNpcStats = &ptrPlayer.getClass().getNpcStats(ptrPlayer); MWMechanics::SkillValue skillValue; - for (int i = 0; i < 27; ++i) + for (int skillIndex = 0; skillIndex < 27; ++skillIndex) { // If the server wants to clear our skill's non-zero modifier, we need to remove // the spell effect causing it, to avoid an infinite loop where the effect keeps resetting // the modifier - if (npcStats.mSkills[i].mMod == 0 && ptrNpcStats->getSkill(i).getModifier() > 0) - ptrNpcStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifySkill, i); + if (npcStats.mSkills[skillIndex].mMod == 0 && ptrNpcStats->getSkill(skillIndex).getModifier() > 0) + { + ptrNpcStats->getActiveSpells().purgeEffectByArg(ESM::MagicEffect::FortifySkill, skillIndex); + MWBase::Environment::get().getMechanicsManager()->updateMagicEffects(ptrPlayer); - skillValue.readState(npcStats.mSkills[i]); - ptrNpcStats->setSkill(i, skillValue); + // Is the modifier for this skill still higher than 0? If so, unequip items that + // fortify the skill + if (ptrNpcStats->getSkill(skillIndex).getModifier() > 0) + { + MechanicsHelper::unequipItemsByEffect(ptrPlayer, ESM::MagicEffect::FortifySkill, -1, skillIndex); + mwmp::Main::get().getGUIController()->refreshGuiMode(MWGui::GM_Inventory); + } + } + + skillValue.readState(npcStats.mSkills[skillIndex]); + ptrNpcStats->setSkill(skillIndex, skillValue); } - for (int i = 0; i < 8; ++i) - ptrNpcStats->setSkillIncrease(i, npcStats.mSkillIncrease[i]); + for (int attributeIndex = 0; attributeIndex < 8; ++attributeIndex) + ptrNpcStats->setSkillIncrease(attributeIndex, npcStats.mSkillIncrease[attributeIndex]); ptrNpcStats->setLevelProgress(npcStats.mLevelProgress); } diff --git a/apps/openmw/mwmp/MechanicsHelper.cpp b/apps/openmw/mwmp/MechanicsHelper.cpp index 9092eec9c..6b880dfd7 100644 --- a/apps/openmw/mwmp/MechanicsHelper.cpp +++ b/apps/openmw/mwmp/MechanicsHelper.cpp @@ -213,3 +213,38 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker) LOG_APPEND(Log::LOG_VERBOSE, " - success: %d", attack.success); } } + +void MechanicsHelper::unequipItemsByEffect(const MWWorld::Ptr& ptr, short effectId, short attributeId, short skillId) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::InventoryStore &ptrInventory = ptr.getClass().getInventoryStore(ptr); + + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++) + { + if (ptrInventory.getSlot(slot) != ptrInventory.end()) + { + MWWorld::ConstContainerStoreIterator itemIterator = ptrInventory.getSlot(slot); + std::string enchantmentName = itemIterator->getClass().getEnchantment(*itemIterator); + + if (!enchantmentName.empty()) + { + const ESM::Enchantment* enchantment = world->getStore().get().find(enchantmentName); + + for (const auto &effect : enchantment->mEffects.mList) + { + if (effect.mEffectID == effectId) + { + if (attributeId == -1 || effect.mAttribute == attributeId) + { + if (skillId == -1 || effect.mSkill == skillId) + { + ptrInventory.unequipSlot(slot, ptr); + break; + } + } + } + } + } + } + } +} diff --git a/apps/openmw/mwmp/MechanicsHelper.hpp b/apps/openmw/mwmp/MechanicsHelper.hpp index e4248241f..0c024cfa9 100644 --- a/apps/openmw/mwmp/MechanicsHelper.hpp +++ b/apps/openmw/mwmp/MechanicsHelper.hpp @@ -23,6 +23,8 @@ namespace MechanicsHelper bool getSpellSuccess(std::string spellId, const MWWorld::Ptr& caster); void processAttack(mwmp::Attack attack, const MWWorld::Ptr& attacker); + + void unequipItemsByEffect(const MWWorld::Ptr& ptr, short effectId, short attributeId = -1, short skillId = -1); }