prevent segfalt in QuickKeysMenu when item has been removed from player inventory

added a MWWorld::ContainerStore to hold item copies which are then used to find
real items with findReplacement().

(storing the RefId could be a better solution but would probably leave tooltips broken...)
pull/456/head
Finbar Crago 7 years ago
parent 64cc3b3a6a
commit da4c55d5ad

@ -124,6 +124,13 @@ namespace MWGui
void QuickKeysMenu::unassign(ItemWidget* key, int index)
{
// cleanup refrance ItemContainer
if( mAssigned[index] == Type_Item || mAssigned[index] == Type_MagicItem)
{
MWWorld::Ptr refItem = *key->getUserData<MWWorld::Ptr>();
mRefItemContainer.remove(refItem.getCellRef().getRefId(), 1, MWMechanics::getPlayer());
}
key->clearUserStrings();
key->setItem(MWWorld::Ptr());
while (key->getChildCount()) // Destroy number label
@ -221,9 +228,11 @@ namespace MWGui
mAssigned[mSelectedIndex] = Type_Item;
button->setItem(item, ItemWidget::Barter);
MWWorld::Ptr itemCopy = *mRefItemContainer.add(item, 1, MWMechanics::getPlayer());
button->setItem(itemCopy, ItemWidget::Barter);
button->setUserString ("ToolTipType", "ItemPtr");
button->setUserData(MWWorld::Ptr(item));
button->setUserData(itemCopy);
if (mItemSelectionDialog)
mItemSelectionDialog->setVisible(false);
@ -334,51 +343,28 @@ namespace MWGui
if (type == Type_Item || type == Type_MagicItem)
{
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
// Make sure the item is available and is not broken
if (item.getRefData().getCount() < 1 ||
(item.getClass().hasItemHealth(item) &&
item.getClass().getItemHealth(item) <= 0))
{
// Try searching for a compatible replacement
std::string id = item.getCellRef().getRefId();
item = store.findReplacement(id);
button->setUserData(MWWorld::Ptr(item));
MWWorld::Ptr refItem = *button->getUserData<MWWorld::Ptr>();
MWWorld::Ptr item = store.findReplacement(refItem.getCellRef().getRefId());
if (item.getRefData().getCount() < 1)
// check the item is available and not broken
if (!item || item.getRefData().getCount() < 1 ||
(item.getClass().hasItemHealth(item) && item.getClass().getItemHealth(item) <= 0))
{
// No replacement was found
MWBase::Environment::get().getWindowManager ()->messageBox (
"#{sQuickMenu5} " + item.getClass().getName(item));
return;
}
}
}
if (type == Type_Magic)
if (!item || item.getRefData().getCount() < 1)
{
std::string spellId = button->getUserString("Spell");
// item not in plater inventory found
MWBase::Environment::get().getWindowManager()->messageBox(
"#{sQuickMenu5} " + refItem.getClass().getName(refItem));
// Make sure the player still has this spell
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
if (!spells.hasSpell(spellId))
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
MWBase::Environment::get().getWindowManager()->messageBox (
"#{sQuickMenu5} " + spell->mName);
return;
}
store.setSelectedEnchantItem(store.end());
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
}
else if (type == Type_Item)
if (type == Type_Item)
{
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
bool isTool = item.getTypeName() == typeid(ESM::Probe).name() || item.getTypeName() == typeid(ESM::Lockpick).name();
bool isTool = item.getTypeName() == typeid(ESM::Probe).name() ||
item.getTypeName() == typeid(ESM::Lockpick).name();
// delay weapon switching if player is busy
if (isDelayNeeded && (isWeapon || isTool))
@ -403,8 +389,6 @@ namespace MWGui
}
else if (type == Type_MagicItem)
{
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
// retrieve ContainerStoreIterator to the item
MWWorld::ContainerStoreIterator it = store.begin();
for (; it != store.end(); ++it)
@ -429,6 +413,25 @@ namespace MWGui
store.setSelectedEnchantItem(it);
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
}
}
else if (type == Type_Magic)
{
std::string spellId = button->getUserString("Spell");
// Make sure the player still has this spell
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
if (!spells.hasSpell(spellId))
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
MWBase::Environment::get().getWindowManager()->messageBox (
"#{sQuickMenu5} " + spell->mName);
return;
}
store.setSelectedEnchantItem(store.end());
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
}
else if (type == Type_HandToHand)
{
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player);

@ -2,6 +2,7 @@
#define MWGUI_QUICKKEYS_H
#include "../mwworld/ptr.hpp"
#include "../mwworld/containerstore.hpp"
#include "windowbase.hpp"
@ -58,6 +59,8 @@ namespace MWGui
MyGUI::EditBox* mInstructionLabel;
MyGUI::Button* mOkButton;
MWWorld::ContainerStore mRefItemContainer;
std::vector<ItemWidget*> mQuickKeyButtons;
std::vector<QuickKeyType> mAssigned;

Loading…
Cancel
Save