diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index adbfca129d..3867cb76a5 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -424,21 +424,10 @@ void OMW::Engine::activate() if (handle.empty()) return; - // the faced handle is not updated immediately, so on a cell change it might - // point to an object that doesn't exist anymore - // therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case - MWWorld::Ptr ptr; - try - { - ptr = MWBase::Environment::get().getWorld()->getPtrViaHandle (handle); + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtrViaHandle (handle); - if (ptr.isEmpty()) - return; - } - catch (std::runtime_error&) - { + if (ptr.isEmpty()) return; - } MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index cef5d6e2e7..192bbd0901 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -70,142 +70,44 @@ namespace MWGui void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender) { + std::string name = mNameEdit->getCaption(); + boost::algorithm::trim(name); + + MWMechanics::Alchemy::Result result = mAlchemy.create (mNameEdit->getCaption ()); + + if (result == MWMechanics::Alchemy::Result_NoName) + { + mWindowManager.messageBox("#{sNotifyMessage37}", std::vector()); + return; + } + // check if mortar & pestle is available (always needed) - /// \todo check albemic, calcinator, retort (sometimes needed) - if (!mApparatus[0]->isUserString("ToolTipType")) + if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle) { mWindowManager.messageBox("#{sNotifyMessage45}", std::vector()); return; } // make sure 2 or more ingredients were selected - int numIngreds = 0; - for (int i=0; i<4; ++i) - if (mIngredients[i]->isUserString("ToolTipType")) - ++numIngreds; - - if (numIngreds < 2) + if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients) { mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector()); return; } - // make sure a name was entered - std::string name = mNameEdit->getCaption(); - boost::algorithm::trim(name); - if (name == "") - { - mWindowManager.messageBox("#{sNotifyMessage37}", std::vector()); - return; - } - - // if there are no created effects, the potion will always fail (but the ingredients won't be destroyed) - if (mEffects.empty()) + if (result == MWMechanics::Alchemy::Result_NoEffects) { mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); return; } - if (rand() % 2 == 0) /// \todo + if (result == MWMechanics::Alchemy::Result_Success) { - ESM::Potion newPotion; - newPotion.mName = mNameEdit->getCaption(); - ESM::EffectList effects; - for (unsigned int i=0; i<4; ++i) - { - if (mEffects.size() >= i+1) - { - ESM::ENAMstruct effect; - effect.mEffectID = mEffects[i].mEffectID; - effect.mArea = 0; - effect.mRange = ESM::RT_Self; - effect.mSkill = mEffects[i].mSkill; - effect.mAttribute = mEffects[i].mAttribute; - effect.mMagnMin = 1; /// \todo - effect.mMagnMax = 10; /// \todo - effect.mDuration = 60; /// \todo - effects.mList.push_back(effect); - } - } - - // UESP Wiki / Morrowind:Alchemy - // "The weight of a potion is an average of the weight of the ingredients, rounded down." - // note by scrawl: not rounding down here, I can't imagine a created potion to - // have 0 weight when using ingredients with 0.1 weight respectively - float weight = 0; - for (int i=0; i<4; ++i) - if (mIngredients[i]->isUserString("ToolTipType")) - weight += mIngredients[i]->getUserData()->get()->base->mData.mWeight; - newPotion.mData.mWeight = weight / float(numIngreds); - - newPotion.mData.mValue = 100; /// \todo - newPotion.mEffects = effects; - // pick a random mesh and icon - std::vector names; - /// \todo is the mesh/icon dependent on alchemy skill? - names.push_back("standard"); - names.push_back("bargain"); - names.push_back("cheap"); - names.push_back("fresh"); - names.push_back("exclusive"); - names.push_back("quality"); - int random = rand() % names.size(); - newPotion.mModel = "m\\misc_potion_" + names[random ] + "_01.nif"; - newPotion.mIcon = "m\\tx_potion_" + names[random ] + "_01.dds"; - - // check if a similiar potion record exists already - bool found = false; - std::string objectId; - typedef std::map PotionMap; - PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list; - for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it) - { - if (found) break; - - if (it->second.mData.mValue == newPotion.mData.mValue - && it->second.mData.mWeight == newPotion.mData.mWeight - && it->second.mName == newPotion.mName - && it->second.mEffects.mList.size() == newPotion.mEffects.mList.size()) - { - // check effects - for (unsigned int i=0; i < it->second.mEffects.mList.size(); ++i) - { - const ESM::ENAMstruct& a = it->second.mEffects.mList[i]; - const ESM::ENAMstruct& b = newPotion.mEffects.mList[i]; - if (a.mEffectID == b.mEffectID - && a.mArea == b.mArea - && a.mRange == b.mRange - && a.mSkill == b.mSkill - && a.mAttribute == b.mAttribute - && a.mMagnMin == b.mMagnMin - && a.mMagnMax == b.mMagnMax - && a.mDuration == b.mDuration) - { - found = true; - objectId = it->first; - break; - } - } - } - } - - if (!found) - { - std::pair result = MWBase::Environment::get().getWorld()->createRecord(newPotion); - objectId = result.first; - } - - // create a reference and add it to player inventory - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId); - MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr); - ref.getPtr().getRefData().setCount(1); - store.add(ref.getPtr()); - mWindowManager.messageBox("#{sPotionSuccess}", std::vector()); MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f); } - else + else if (result == MWMechanics::Alchemy::Result_RandomFailure) { // potion failed mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); @@ -229,7 +131,7 @@ namespace MWGui { openContainer (MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); // this sets mPtr setFilter (ContainerBase::Filter_Ingredients); - + mAlchemy.setAlchemist (mPtr); int index = 0; @@ -277,6 +179,9 @@ namespace MWGui if (!mIngredients[i]->isUserString("ToolTipType")) { add = mIngredients[i]; + + mAlchemy.addIngredient(item); + break; } @@ -306,8 +211,6 @@ namespace MWGui void AlchemyWindow::update() { - Widgets::SpellEffectList effects; - for (int i=0; i<4; ++i) { MyGUI::ImageBox* ingredient = mIngredients[i]; @@ -315,19 +218,6 @@ namespace MWGui if (!ingredient->isUserString("ToolTipType")) continue; - // add the effects of this ingredient to list of effects - MWWorld::LiveCellRef* ref = ingredient->getUserData()->get(); - for (int i=0; i<4; ++i) - { - if (ref->base->mData.mEffectID[i] < 0) - continue; - MWGui::Widgets::SpellEffectParams params; - params.mEffectID = ref->base->mData.mEffectID[i]; - params.mAttribute = ref->base->mData.mAttributes[i]; - params.mSkill = ref->base->mData.mSkills[i]; - effects.push_back(params); - } - // update ingredient count labels if (ingredient->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); @@ -340,50 +230,14 @@ namespace MWGui text->setCaption(getCountString(ingredient->getUserData()->getRefData().getCount())); } - // now remove effects that are only present once - Widgets::SpellEffectList::iterator it = effects.begin(); - while (it != effects.end()) + std::vector effects; + ESM::EffectList list; + list.mList = effects; + for (MWMechanics::Alchemy::TEffectsIterator it = mAlchemy.beginEffects (); it != mAlchemy.endEffects (); ++it) { - Widgets::SpellEffectList::iterator next = it; - ++next; - bool found = false; - for (; next != effects.end(); ++next) - { - if (*next == *it) - found = true; - } - - if (!found) - it = effects.erase(it); - else - ++it; + list.mList.push_back(*it); } - // now remove duplicates, and don't allow more than 4 effects - Widgets::SpellEffectList old = effects; - effects.clear(); - int i=0; - for (Widgets::SpellEffectList::iterator it = old.begin(); - it != old.end(); ++it) - { - bool found = false; - for (Widgets::SpellEffectList::iterator it2 = effects.begin(); - it2 != effects.end(); ++it2) - { - // MW considers all "foritfy attribute" effects as the same effect. See the - // "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy - // thus, we are only checking effectID here and not attribute or skill - if (it2->mEffectID == it->mEffectID) - found = true; - } - if (!found && i<4) - { - ++i; - effects.push_back(*it); - } - } - mEffects = effects; - while (mEffectsBox->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0)); @@ -391,7 +245,9 @@ namespace MWGui Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget ("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top); effectsWidget->setWindowManager(&mWindowManager); - effectsWidget->setEffectList(effects); + + Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list); + effectsWidget->setEffectList(_list); std::vector effectItems; effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0); @@ -404,5 +260,9 @@ namespace MWGui static_cast(ingredient)->setImageTexture(""); if (ingredient->getChildCount()) MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0)); + + for (int i=0; i<4; ++i) + if (mIngredients[i] == ingredient) + mAlchemy.removeIngredient (i); } } diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 179cdd174f..5f84e73e9b 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -26,8 +26,6 @@ namespace MWGui MyGUI::EditBox* mNameEdit; - Widgets::SpellEffectList mEffects; // effects of created potion - void onCancelButtonClicked(MyGUI::Widget* _sender); void onCreateButtonClicked(MyGUI::Widget* _sender); void onIngredientSelected(MyGUI::Widget* _sender); @@ -41,12 +39,12 @@ namespace MWGui void update(); - private: - - MWMechanics::Alchemy mAlchemy; + private: - std::vector mApparatus; - std::vector mIngredients; + MWMechanics::Alchemy mAlchemy; + + std::vector mApparatus; + std::vector mIngredients; }; } diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 39afba7497..5256028ebb 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -79,14 +79,10 @@ void ToolTips::onFrame(float frameDuration) || (mWindowManager->getMode() == GM_Inventory))) { std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); - try - { - mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); - } - catch (std::exception /* & e */) - { + + mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle); + if (mFocusObject.isEmpty ()) return; - } MyGUI::IntSize tooltipSize = getToolTipViaPtr(true); diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index e37a302108..583a3c18e6 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -62,6 +62,9 @@ void MWMechanics::Alchemy::filterEffects (std::set& effects) const { bool found = false; + if (iter->isEmpty()) + continue; + const MWWorld::LiveCellRef *ingredient = iter->get(); for (int i=0; i<4; ++i) @@ -178,7 +181,7 @@ void MWMechanics::Alchemy::updateEffects() throw std::runtime_error ("invalid base cost for magic effect " + iter->mId); float fPotionT1MagMul = - MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1MagMul")->getFloat(); + MWBase::Environment::get().getWorld()->getStore().gameSettings.find ("fPotionT1MagMult")->getFloat(); if (fPotionT1MagMul<=0) throw std::runtime_error ("invalid gmst: fPotionT1MagMul"); @@ -189,15 +192,15 @@ void MWMechanics::Alchemy::updateEffects() if (fPotionT1DurMult<=0) throw std::runtime_error ("invalid gmst: fPotionT1DurMult"); - float magnitude = magicEffect->mData.mFlags && ESM::MagicEffect::NoMagnitude ? + float magnitude = magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude ? 1 : (x / fPotionT1MagMul) / magicEffect->mData.mBaseCost; - float duration = magicEffect->mData.mFlags && ESM::MagicEffect::NoDuration ? + float duration = magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration ? 1 : (x / fPotionT1DurMult) / magicEffect->mData.mBaseCost; - if (!(magicEffect->mData.mFlags && ESM::MagicEffect::NoMagnitude)) + if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)) applyTools (magicEffect->mData.mFlags, magnitude); - if (!(magicEffect->mData.mFlags && ESM::MagicEffect::NoDuration)) + if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) applyTools (magicEffect->mData.mFlags, duration); duration = static_cast (duration+0.5); @@ -471,7 +474,7 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na if (beginEffects()==endEffects()) return Result_NoEffects; - if (getChance() (RAND_MAX)*100) + if (getChance() (RAND_MAX)) { removeIngredients(); return Result_RandomFailure; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6fc228f0b5..8d8542bb58 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -339,7 +339,7 @@ namespace MWWorld return ptr; } - throw std::runtime_error ("unknown Ogre handle: " + handle); + return MWWorld::Ptr(); } void World::enable (const Ptr& reference) @@ -850,12 +850,13 @@ namespace MWWorld mWeatherManager->update (duration); // inform the GUI about focused object - try - { - MWWorld::Ptr object = getPtrViaHandle(mFacedHandle); - MWBase::Environment::get().getWindowManager()->setFocusObject(object); + MWWorld::Ptr object = getPtrViaHandle(mFacedHandle); - // retrieve object dimensions so we know where to place the floating label + MWBase::Environment::get().getWindowManager()->setFocusObject(object); + + // retrieve object dimensions so we know where to place the floating label + if (!object.isEmpty ()) + { Ogre::SceneNode* node = object.getRefData().getBaseNode(); Ogre::AxisAlignedBox bounds; int i; @@ -871,11 +872,6 @@ namespace MWWorld screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]); } } - catch (std::runtime_error&) - { - MWWorld::Ptr null; - MWBase::Environment::get().getWindowManager()->setFocusObject(null); - } if (!mRendering->occlusionQuerySupported()) {