From c0b0227e8a494ea27cdc0c82df20ff4929e015d6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 16 Mar 2013 19:00:14 +0100 Subject: [PATCH 01/47] enchanting --- apps/openmw/mwclass/armor.cpp | 8 ++ apps/openmw/mwclass/armor.hpp | 2 + apps/openmw/mwclass/clothing.cpp | 8 ++ apps/openmw/mwclass/clothing.hpp | 2 + apps/openmw/mwclass/weapon.cpp | 8 ++ apps/openmw/mwclass/weapon.hpp | 2 + apps/openmw/mwgui/container.cpp | 70 ++++++++--- apps/openmw/mwgui/container.hpp | 23 ++-- apps/openmw/mwgui/dialogue.cpp | 4 +- apps/openmw/mwgui/enchantingdialog.cpp | 130 ++++++++++++++++++++ apps/openmw/mwgui/enchantingdialog.hpp | 31 +++++ apps/openmw/mwgui/itemselection.cpp | 2 +- apps/openmw/mwgui/itemselection.hpp | 2 +- apps/openmw/mwworld/class.cpp | 5 + apps/openmw/mwworld/class.hpp | 3 + files/mygui/openmw_chargen_race.layout | 6 +- files/mygui/openmw_enchanting_dialog.layout | 15 ++- 17 files changed, 281 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index fdf211c28a..130c0515d0 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -290,4 +290,12 @@ namespace MWClass return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell); } + + short Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mData.mEnchant; + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 51c0ea21c9..ff45411ed2 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -70,6 +70,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index dfced6daa8..f5f71a7767 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -238,4 +238,12 @@ namespace MWClass return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell); } + + short Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mData.mEnchant; + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index f7801848f6..f01c78afce 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -64,6 +64,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 475c08ccbf..0f6e86811e 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -378,4 +378,12 @@ namespace MWClass return MWWorld::Ptr(&cell.mWeapons.insert(*ref), &cell); } + + short Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mData.mEnchant; + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 06cf88c5f2..bf34172516 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -70,6 +70,8 @@ namespace MWClass ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 2b80003127..1b4a982765 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -68,6 +68,16 @@ namespace return compareType(left.getTypeName(), right.getTypeName()); } } + + bool isChargedSoulstone (MWWorld::Ptr ptr) + { + if (ptr.getTypeName() != typeid(ESM::Miscellaneous).name()) + return false; + MWWorld::LiveCellRef *ref = + ptr.get(); + + return (ref->mRef.mSoul != ""); + } } @@ -345,7 +355,7 @@ void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel) mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0)); } -void ContainerBase::setFilter(ContainerBase::Filter filter) +void ContainerBase::setFilter(int filter) { mFilter = filter; drawItems(); @@ -369,29 +379,34 @@ void ContainerBase::drawItems() int maxHeight = mItemView->getSize().height - 58; bool onlyMagic = false; + bool noMagic = false; int categories = 0; - if (mFilter == Filter_All) - categories = MWWorld::ContainerStore::Type_All; - else if (mFilter == Filter_Weapon) - categories = MWWorld::ContainerStore::Type_Weapon; - else if (mFilter == Filter_Apparel) - categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor; - else if (mFilter == Filter_Magic) + if (mFilter & Filter_All) + categories |= MWWorld::ContainerStore::Type_All; + if (mFilter & Filter_Weapon) + categories |= MWWorld::ContainerStore::Type_Weapon; + if (mFilter & Filter_Apparel) + categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor; + if (mFilter & Filter_Magic) { - categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor - + MWWorld::ContainerStore::Type_Weapon + MWWorld::ContainerStore::Type_Book - + MWWorld::ContainerStore::Type_Potion; + categories |= MWWorld::ContainerStore::Type_Clothing | MWWorld::ContainerStore::Type_Armor + | MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Book + | MWWorld::ContainerStore::Type_Potion; onlyMagic = true; } - else if (mFilter == Filter_Misc) + if (mFilter & Filter_Misc) { - categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book - + MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair - + MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light - + MWWorld::ContainerStore::Type_Apparatus + MWWorld::ContainerStore::Type_Probe; + categories |= MWWorld::ContainerStore::Type_Miscellaneous | MWWorld::ContainerStore::Type_Book + | MWWorld::ContainerStore::Type_Ingredient | MWWorld::ContainerStore::Type_Repair + | MWWorld::ContainerStore::Type_Lockpick | MWWorld::ContainerStore::Type_Light + | MWWorld::ContainerStore::Type_Apparatus | MWWorld::ContainerStore::Type_Probe; } - else if (mFilter == Filter_Ingredients) - categories = MWWorld::ContainerStore::Type_Ingredient; + if (mFilter & Filter_Ingredients) + categories |= MWWorld::ContainerStore::Type_Ingredient; + if (mFilter & Filter_ChargedSoulstones) + categories |= MWWorld::ContainerStore::Type_Miscellaneous; + if (mFilter & Filter_NoMagic) + noMagic = true; /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them @@ -466,12 +481,29 @@ void ContainerBase::drawItems() { const MWWorld::Ptr* iter = &((*it).first); + + if (onlyMagic + && it->second != ItemState_Barter + && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" + && iter->getTypeName() != typeid(ESM::Potion).name()) + continue; + + if (noMagic + && it->second != ItemState_Barter + && (MWWorld::Class::get(*iter).getEnchantment(*iter) != "" + || iter->getTypeName() == typeid(ESM::Potion).name())) + continue; + + if ( (mFilter & Filter_ChargedSoulstones) + && !isChargedSoulstone(*iter)) + continue; + int displayCount = iter->getRefData().getCount(); if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData()) { displayCount -= mDragAndDrop->mDraggedCount; } - if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) + if(displayCount > 0) { std::string path = std::string("icons\\"); path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 3c8127b26c..49e60aa251 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -48,16 +48,17 @@ namespace MWGui ContainerBase(DragAndDrop* dragAndDrop); virtual ~ContainerBase(); - enum Filter - { - Filter_All = 0x01, - Filter_Weapon = 0x02, - Filter_Apparel = 0x03, - Filter_Magic = 0x04, - Filter_Misc = 0x05, + // basic types (inclusive) + static const int Filter_All = (1<<0); + static const int Filter_Weapon = (1<<1); + static const int Filter_Apparel = (1<<2); + static const int Filter_Ingredients = (1<<3); + static const int Filter_Misc = (1<<4); - Filter_Ingredients = 0x06 - }; + // special filtering (exclusive) + static const int Filter_Magic = (1<<5); + static const int Filter_NoMagic = (1<<6); + static const int Filter_ChargedSoulstones = (1<<7); enum ItemState { @@ -78,7 +79,7 @@ namespace MWGui MWWorld::ContainerStore& getBoughtItems() { return mBoughtItems; } void openContainer(MWWorld::Ptr container); - void setFilter(Filter filter); ///< set category filter + void setFilter(int filter); ///< set category filter void drawItems(); protected: @@ -92,7 +93,7 @@ namespace MWGui DragAndDrop* mDragAndDrop; - Filter mFilter; + int mFilter; // bought items are put in a separate ContainerStore so that they don't stack with other (not bought) items. MWWorld::ContainerStore mBoughtItems; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index cdcbfc4d18..d4125a05f0 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -316,8 +316,8 @@ void DialogueWindow::setKeywords(std::list keyWords) if (mServices & Service_CreateSpells) mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString()); -// if (mServices & Service_Enchant) -// mTopicsList->addItem(gmst.find("sEnchanting")->getString()); + if (mServices & Service_Enchant) + mTopicsList->addItem(gmst.find("sEnchanting")->getString()); if (mServices & Service_Training) mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString()); diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 3bd67ade63..673739cbf3 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -1,5 +1,13 @@ #include "enchantingdialog.hpp" +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" +#include "../mwworld/player.hpp" + +#include "itemselection.hpp" +#include "container.hpp" namespace MWGui { @@ -8,19 +16,45 @@ namespace MWGui EnchantingDialog::EnchantingDialog(MWBase::WindowManager &parWindowManager) : WindowBase("openmw_enchanting_dialog.layout", parWindowManager) , EffectEditorBase(parWindowManager) + , mItemSelectionDialog(NULL) + , mCurrentEnchantmentPoints(0) { getWidget(mCancelButton, "CancelButton"); getWidget(mAvailableEffectsList, "AvailableEffects"); getWidget(mUsedEffectsView, "UsedEffects"); + getWidget(mItemBox, "ItemBox"); + getWidget(mSoulBox, "SoulBox"); + getWidget(mEnchantmentPoints, "Enchantment"); + getWidget(mCastCost, "CastCost"); + getWidget(mCharge, "Charge"); + getWidget(mTypeButton, "TypeButton"); + getWidget(mBuyButton, "BuyButton"); + getWidget(mPrice, "PriceLabel"); setWidgets(mAvailableEffectsList, mUsedEffectsView); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onCancelButtonClicked); + mItemBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectItem); + mSoulBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectSoul); + } + + EnchantingDialog::~EnchantingDialog() + { + delete mItemSelectionDialog; } void EnchantingDialog::open() { center(); + onRemoveItem(NULL); + onRemoveSoul(NULL); + } + + void EnchantingDialog::updateLabels() + { + mEnchantmentPoints->setCaption(boost::lexical_cast(mCurrentEnchantmentPoints) + + " / " + (mItem.isEmpty() ? "0" : boost::lexical_cast( + MWWorld::Class::get(mItem).getEnchantmentPoints(mItem)))); } void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) @@ -40,4 +74,100 @@ namespace MWGui { mWindowManager.removeGuiMode (GM_Enchanting); } + + void EnchantingDialog::onSelectItem(MyGUI::Widget *sender) + { + delete mItemSelectionDialog; + mItemSelectionDialog = new ItemSelectionDialog("#{sEnchantItems}", + ContainerBase::Filter_Apparel|ContainerBase::Filter_Weapon|ContainerBase::Filter_NoMagic, mWindowManager); + mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onItemSelected); + mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onItemCancel); + mItemSelectionDialog->setVisible(true); + mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + mItemSelectionDialog->drawItems (); + } + + void EnchantingDialog::onItemSelected(MWWorld::Ptr item) + { + mItemSelectionDialog->setVisible(false); + + while (mItemBox->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0)); + + MyGUI::ImageBox* image = mItemBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(item).getInventoryIcon(item); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture (path); + image->setUserString ("ToolTipType", "ItemPtr"); + image->setUserData(item); + image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem); + + mItem = item; + updateLabels(); + } + + void EnchantingDialog::onRemoveItem(MyGUI::Widget *sender) + { + while (mItemBox->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0)); + mItem = MWWorld::Ptr(); + updateLabels(); + } + + void EnchantingDialog::onItemCancel() + { + mItemSelectionDialog->setVisible(false); + } + + void EnchantingDialog::onSoulSelected(MWWorld::Ptr item) + { + mItemSelectionDialog->setVisible(false); + + while (mSoulBox->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); + + MyGUI::ImageBox* image = mSoulBox->createWidget("ImageBox", MyGUI::IntCoord(0, 0, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(item).getInventoryIcon(item); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + image->setImageTexture (path); + image->setUserString ("ToolTipType", "ItemPtr"); + image->setUserData(item); + image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul); + + mSoul = item; + updateLabels(); + } + + void EnchantingDialog::onRemoveSoul(MyGUI::Widget *sender) + { + while (mSoulBox->getChildCount ()) + MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); + mSoul = MWWorld::Ptr(); + updateLabels(); + } + + void EnchantingDialog::onSoulCancel() + { + mItemSelectionDialog->setVisible(false); + } + + void EnchantingDialog::onSelectSoul(MyGUI::Widget *sender) + { + delete mItemSelectionDialog; + mItemSelectionDialog = new ItemSelectionDialog("#{sSoulGemsWithSouls}", + ContainerBase::Filter_Misc|ContainerBase::Filter_ChargedSoulstones, mWindowManager); + mItemSelectionDialog->eventItemSelected += MyGUI::newDelegate(this, &EnchantingDialog::onSoulSelected); + mItemSelectionDialog->eventDialogCanceled += MyGUI::newDelegate(this, &EnchantingDialog::onSoulCancel); + mItemSelectionDialog->setVisible(true); + mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + mItemSelectionDialog->drawItems (); + + //mWindowManager.messageBox("#{sInventorySelectNoSoul}"); + } } diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 0415c9d8df..bcebb799df 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -10,10 +10,13 @@ namespace MWGui { + class ItemSelectionDialog; + class EnchantingDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase { public: EnchantingDialog(MWBase::WindowManager& parWindowManager); + virtual ~EnchantingDialog(); virtual void open(); void startEnchanting(MWWorld::Ptr actor); @@ -22,8 +25,36 @@ namespace MWGui virtual void onReferenceUnavailable(); void onCancelButtonClicked(MyGUI::Widget* sender); + void onSelectItem (MyGUI::Widget* sender); + void onSelectSoul (MyGUI::Widget* sender); + void onRemoveItem (MyGUI::Widget* sender); + void onRemoveSoul (MyGUI::Widget* sender); + + void onItemSelected(MWWorld::Ptr item); + void onItemCancel(); + void onSoulSelected(MWWorld::Ptr item); + void onSoulCancel(); + + void updateLabels(); + + ItemSelectionDialog* mItemSelectionDialog; MyGUI::Button* mCancelButton; + MyGUI::ImageBox* mItemBox; + MyGUI::ImageBox* mSoulBox; + + MyGUI::Button* mTypeButton; + MyGUI::Button* mBuyButton; + + MyGUI::TextBox* mEnchantmentPoints; + MyGUI::TextBox* mCastCost; + MyGUI::TextBox* mCharge; + MyGUI::TextBox* mPrice; + + MWWorld::Ptr mItem; + MWWorld::Ptr mSoul; + + float mCurrentEnchantmentPoints; }; } diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp index 14b1cf8ee5..4b8adcef4f 100644 --- a/apps/openmw/mwgui/itemselection.cpp +++ b/apps/openmw/mwgui/itemselection.cpp @@ -3,7 +3,7 @@ namespace MWGui { - ItemSelectionDialog::ItemSelectionDialog(const std::string &label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager) + ItemSelectionDialog::ItemSelectionDialog(const std::string &label, int filter, MWBase::WindowManager& parWindowManager) : ContainerBase(NULL) , WindowModal("openmw_itemselection_dialog.layout", parWindowManager) { diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp index cab125f1f8..733daa91ae 100644 --- a/apps/openmw/mwgui/itemselection.hpp +++ b/apps/openmw/mwgui/itemselection.hpp @@ -8,7 +8,7 @@ namespace MWGui class ItemSelectionDialog : public ContainerBase, public WindowModal { public: - ItemSelectionDialog(const std::string& label, ContainerBase::Filter filter, MWBase::WindowManager& parWindowManager); + ItemSelectionDialog(const std::string& label, int filter, MWBase::WindowManager& parWindowManager); typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Item; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 71b24b65dc..cc20aeda75 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -127,6 +127,11 @@ namespace MWWorld return 0; } + short Class::getEnchantmentPoints (const MWWorld::Ptr& ptr) const + { + throw std::runtime_error ("class does not support enchanting"); + } + MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const { throw std::runtime_error ("movement settings not supported by class"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 1a6a16ca07..77c29fe489 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -222,6 +222,9 @@ namespace MWWorld ///< @return the enchantment ID if the object is enchanted, otherwise an empty string /// (default implementation: return empty string) + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; + ///< @return the number of enchantment points available for possible enchanting + virtual void adjustScale(const MWWorld::Ptr& ptr,float& scale) const; virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const; diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index 4ef8da0f3f..c0b04618ed 100644 --- a/files/mygui/openmw_chargen_race.layout +++ b/files/mygui/openmw_chargen_race.layout @@ -22,7 +22,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -46,7 +46,7 @@ - + diff --git a/files/mygui/openmw_enchanting_dialog.layout b/files/mygui/openmw_enchanting_dialog.layout index a19c569256..2549fd26f9 100644 --- a/files/mygui/openmw_enchanting_dialog.layout +++ b/files/mygui/openmw_enchanting_dialog.layout @@ -26,14 +26,18 @@ - + + + - + + + @@ -85,7 +89,11 @@ - + + + + + @@ -97,6 +105,7 @@ + From ad3478c8f276dc6c9546ef9fb79fbd322e565bef Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 17 Mar 2013 02:02:09 +0100 Subject: [PATCH 02/47] Fix inverted dialogue functions (NotClass etc.) The comparison present is useless for these functions. --- apps/openmw/mwdialogue/filter.cpp | 11 +++++++++-- apps/openmw/mwdialogue/selectwrapper.cpp | 25 +++++++++++++----------- apps/openmw/mwdialogue/selectwrapper.hpp | 5 ++--- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 7b5f354a23..8e8ac4db5e 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -136,8 +136,12 @@ bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info, bool invert bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const { - if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name()) - return select.isInverted(); + if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name())) + // If the actor is a creature, we do not test the conditions applicable + // only to NPCs. Such conditions can never be satisfied, apart + // inverted ones (NotClass, NotRace, NotFaction return true + // because creatures are not of any race, class or faction). + return select.getType() == SelectWrapper::Type_Inverted; switch (select.getType()) { @@ -145,6 +149,9 @@ bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); + + // We must not do the comparison for inverted functions (eg. Function_NotClass) + case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select); } return true; diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 77930ae423..81a4153601 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -219,7 +219,6 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const static const Function booleanFunctions[] = { Function_False, - Function_NotId, Function_NotFaction, Function_NotClass, Function_NotRace, Function_NotCell, Function_SameGender, Function_SameRace, Function_SameFaction, Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus, Function_PcExpelled, @@ -231,6 +230,13 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const Function_None // end marker }; + static const Function invertedBooleanFunctions[] = + { + Function_NotId, Function_NotFaction, Function_NotClass, + Function_NotRace, Function_NotCell, + Function_None // end marker + }; + Function function = getFunction(); for (int i=0; integerFunctions[i]!=Function_None; ++i) @@ -245,16 +251,13 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const if (booleanFunctions[i]==function) return Type_Boolean; + for (int i=0; invertedBooleanFunctions[i]!=Function_None; ++i) + if (invertedBooleanFunctions[i]==function) + return Type_Inverted; + return Type_None; } -bool MWDialogue::SelectWrapper::isInverted() const -{ - char type = mSelect.mSelectRule[1]; - - return type=='7' || type=='8' || type=='9' || type=='A' || type=='B' || type=='C'; -} - bool MWDialogue::SelectWrapper::isNpcOnly() const { static const Function functions[] = @@ -283,17 +286,17 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const bool MWDialogue::SelectWrapper::selectCompare (int value) const { - return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR + return selectCompareImp (mSelect, value); } bool MWDialogue::SelectWrapper::selectCompare (float value) const { - return selectCompareImp (mSelect, value)!=isInverted(); // logic XOR + return selectCompareImp (mSelect, value); } bool MWDialogue::SelectWrapper::selectCompare (bool value) const { - return selectCompareImp (mSelect, static_cast (value))!=isInverted(); // logic XOR + return selectCompareImp (mSelect, static_cast (value)); } std::string MWDialogue::SelectWrapper::getName() const diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index c27339afa0..0548c60cbb 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -50,7 +50,8 @@ namespace MWDialogue Type_None, Type_Integer, Type_Numeric, - Type_Boolean + Type_Boolean, + Type_Inverted }; private: @@ -67,8 +68,6 @@ namespace MWDialogue Type getType() const; - bool isInverted() const; - bool isNpcOnly() const; ///< \attention Do not call any of the select functions for this select struct! From f25b56ac8867b32584295baa1112ffadf6e33187 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 17 Mar 2013 02:06:06 +0100 Subject: [PATCH 03/47] Add dialogue function: NotLocal --- apps/openmw/mwdialogue/filter.cpp | 24 ++++++++++++++++++++++++ apps/openmw/mwdialogue/selectwrapper.cpp | 4 ++-- apps/openmw/mwdialogue/selectwrapper.hpp | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 8e8ac4db5e..c2d0515dd7 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -440,6 +440,30 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co return Misc::StringUtils::lowerCase (mActor.getCell()->mCell->mName)!=select.getName(); + case SelectWrapper::Function_NotLocal: + { + std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); + + if (scriptName.empty()) + // This actor has no attached script, so there is no local variable + return true; + + const ESM::Script *script = + MWBase::Environment::get().getWorld()->getStore().get().find (scriptName); + + std::string name = select.getName(); + + int i = 0; + for (; i < script->mVarNames.size(); ++i) + if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name) + break; + + if (i >= script->mVarNames.size()) + return true; // script does not have a variable of this name + + return false; + } + case SelectWrapper::Function_SameGender: return (player.get()->mBase->mFlags & ESM::NPC::Female)== diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 81a4153601..d48a06323e 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -117,7 +117,7 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() con case '9': return Function_NotClass; case 'A': return Function_NotRace; case 'B': return Function_NotCell; - case 'C': return Function_Local; + case 'C': return Function_NotLocal; } return Function_None; @@ -233,7 +233,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const static const Function invertedBooleanFunctions[] = { Function_NotId, Function_NotFaction, Function_NotClass, - Function_NotRace, Function_NotCell, + Function_NotRace, Function_NotCell, Function_NotLocal, Function_None // end marker }; diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index 0548c60cbb..f4bc898a4b 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -22,6 +22,7 @@ namespace MWDialogue Function_NotClass, Function_NotRace, Function_NotCell, + Function_NotLocal, Function_Local, Function_Global, Function_SameGender, Function_SameRace, Function_SameFaction, From 8de93db488dba3f9543c9a73a2824613d89e8f15 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 17 Mar 2013 02:06:36 +0100 Subject: [PATCH 04/47] Coding style consistence --- apps/openmw/mwdialogue/selectwrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index d48a06323e..64bd1d2449 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -262,7 +262,7 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const { static const Function functions[] = { - Function_NotFaction, SelectWrapper::Function_NotClass, SelectWrapper::Function_NotRace, + Function_NotFaction, Function_NotClass, Function_NotRace, Function_SameGender, Function_SameRace, Function_SameFaction, Function_PcSkill, Function_PcExpelled, From 6783ff67483b5a227975f1ce76d35f3713e89caa Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 17 Mar 2013 03:17:05 +0100 Subject: [PATCH 05/47] Workaround to have dialogues until actor detection is implemented for NPCs --- apps/openmw/mwworld/class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 985d35d45e..108efddd81 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -169,7 +169,7 @@ namespace MWWorld bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const { - return false; + return true; } float Class::getArmorRating (const MWWorld::Ptr& ptr) const From cd84b68e4b58572cf0e896c83f4968ee41c65e55 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 20 Mar 2013 20:55:48 +0100 Subject: [PATCH 06/47] silencing some warnings --- apps/openmw/mwdialogue/filter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index c2d0515dd7..cd9908d3df 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -454,11 +454,11 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co std::string name = select.getName(); int i = 0; - for (; i < script->mVarNames.size(); ++i) + for (; i < static_cast (script->mVarNames.size()); ++i) if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name) break; - if (i >= script->mVarNames.size()) + if (i >= static_cast (script->mVarNames.size())) return true; // script does not have a variable of this name return false; From d05508db52c52f5a3973c387fe5e21864859e70d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 10:07:25 +0100 Subject: [PATCH 07/47] switching editor id tables from QAbstractTableModel to QAbstractItemModel (in preparation for record types like containers) --- apps/opencs/model/world/commands.cpp | 2 +- apps/opencs/model/world/data.cpp | 10 +++++----- apps/opencs/model/world/data.hpp | 10 +++++----- apps/opencs/model/world/idtable.cpp | 19 +++++++++++++++++++ apps/opencs/model/world/idtable.hpp | 9 +++++++-- apps/opencs/view/world/dialoguesubview.cpp | 4 ++-- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index e22ecf9921..1f8660bdde 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -1,7 +1,7 @@ #include "commands.hpp" -#include +#include #include "idtableproxymodel.hpp" #include "idtable.hpp" diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index bbd8667b34..06e638b07f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -3,7 +3,7 @@ #include -#include +#include #include #include @@ -12,7 +12,7 @@ #include "idtable.hpp" #include "columns.hpp" -void CSMWorld::Data::addModel (QAbstractTableModel *model, UniversalId::Type type1, +void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1, UniversalId::Type type2) { mModels.push_back (model); @@ -42,7 +42,7 @@ CSMWorld::Data::Data() CSMWorld::Data::~Data() { - for (std::vector::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) + for (std::vector::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) delete *iter; } @@ -66,9 +66,9 @@ CSMWorld::IdCollection& CSMWorld::Data::getGmsts() return mGmsts; } -QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) +QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { - std::map::iterator iter = mModelIndex.find (id.getType()); + std::map::iterator iter = mModelIndex.find (id.getType()); if (iter==mModelIndex.end()) throw std::logic_error ("No table model available for " + id.toString()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 3745346511..e42d5c1026 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -12,7 +12,7 @@ #include "idcollection.hpp" #include "universalid.hpp" -class QAbstractTableModel; +class QAbstractItemModel; namespace CSMWorld { @@ -20,14 +20,14 @@ namespace CSMWorld { IdCollection mGlobals; IdCollection mGmsts; - std::vector mModels; - std::map mModelIndex; + std::vector mModels; + std::map mModelIndex; // not implemented Data (const Data&); Data& operator= (const Data&); - void addModel (QAbstractTableModel *model, UniversalId::Type type1, + void addModel (QAbstractItemModel *model, UniversalId::Type type1, UniversalId::Type type2 = UniversalId::Type_None); public: @@ -44,7 +44,7 @@ namespace CSMWorld IdCollection& getGmsts(); - QAbstractTableModel *getTableModel (const UniversalId& id); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// /// \note The returned table may either be the model for the ID itself or the model that diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index afed6b6eda..79e33584b2 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -96,6 +96,25 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren return true; } +QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const +{ + if (parent.isValid()) + return QModelIndex(); + + if (row<0 || row>=mIdCollection->getSize()) + return QModelIndex(); + + if (column<0 || column>=mIdCollection->getColumns()) + return QModelIndex(); + + return createIndex (row, column); +} + +QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const +{ + return QModelIndex(); +} + void CSMWorld::IdTable::addRecord (const std::string& id) { int index = mIdCollection->getSize(); diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index deaebaa38a..80476c5243 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -1,14 +1,14 @@ #ifndef CSM_WOLRD_IDTABLE_H #define CSM_WOLRD_IDTABLE_H -#include +#include namespace CSMWorld { class IdCollectionBase; class RecordBase; - class IdTable : public QAbstractTableModel + class IdTable : public QAbstractItemModel { Q_OBJECT @@ -39,6 +39,11 @@ namespace CSMWorld virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) + const; + + virtual QModelIndex parent (const QModelIndex& index) const; + void addRecord (const std::string& id); QModelIndex getModelIndex (const std::string& id, int column) const; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index e16de99eff..cedb20de92 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -24,7 +24,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM widget->setLayout (layout); - QAbstractTableModel *model = document.getData().getTableModel (id); + QAbstractItemModel *model = document.getData().getTableModel (id); int columns = model->columnCount(); From 5346508471d6339bc251679fb284b56aaed5ca29 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 10:16:32 +0100 Subject: [PATCH 08/47] added kate junk to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 776e2b6591..27d3a13de3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ data CMakeLists.txt.user *.swp *.swo +*.kate-swp From ebb1dab8e12a593e8862ff75759c32597bac4316 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 10:19:07 +0100 Subject: [PATCH 09/47] removed debugging leftovers --- apps/opencs/model/doc/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 7a88335c89..c6b8bbc73d 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2,7 +2,7 @@ #include "document.hpp" #include -#include + void CSMDoc::Document::load (const std::vector::const_iterator& begin, const std::vector::const_iterator& end, bool lastAsModified) { From cafbabde457172584c3e776b587a52975daec96a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 12:13:32 +0100 Subject: [PATCH 10/47] fixed broken loading of single files into the editor --- apps/opencs/model/doc/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index c6b8bbc73d..47cf1f6642 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -214,7 +214,7 @@ CSMDoc::Document::Document (const std::vector& files, b if (new_ && files.size()==1) createBase(); - else if (files.size()>1) + else { std::vector::const_iterator end = files.end(); From 9464f45d57aacbb16455ff58755f4af46e8feb8b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 12:47:22 +0100 Subject: [PATCH 11/47] fixed an encoding problem. I hate you QString. I hate you so much --- apps/opencs/model/world/columns.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 018825831b..1492e96b7d 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -35,7 +35,7 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - return record.get().mId.c_str(); + return QString::fromUtf8 (record.get().mId.c_str()); } virtual bool isEditable() const @@ -127,17 +127,17 @@ namespace CSMWorld { case ESM::VT_String: - return record.get().mValue.getString().c_str(); break; + return QString::fromUtf8 (record.get().mValue.getString().c_str()); case ESM::VT_Int: case ESM::VT_Short: case ESM::VT_Long: - return record.get().mValue.getInteger(); break; + return record.get().mValue.getInteger(); case ESM::VT_Float: - return record.get().mValue.getFloat(); break; + return record.get().mValue.getFloat(); default: return QVariant(); } From 1d1471b81c9b35f9faabdbbf575151491bf2701c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 12:57:10 +0100 Subject: [PATCH 12/47] fixed a bug in ESM::Variant::write (was affecting string values) --- components/esm/variant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp index d25072e548..a7859d1283 100644 --- a/components/esm/variant.cpp +++ b/components/esm/variant.cpp @@ -186,7 +186,7 @@ void ESM::Variant::write (std::ostream& stream) const case VT_String: - stream << "variant string: \"" << mData->getString() << "\2"; + stream << "variant string: \"" << mData->getString() << "\""; break; } } From a955068853b0a4aa83ff31df5dfc492f24fc6b1b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 13:40:55 +0100 Subject: [PATCH 13/47] added universal IDs for skills --- apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index c006852bc6..6fce376bea 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -19,6 +19,7 @@ namespace { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -27,6 +28,7 @@ namespace { { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 9ff7d17b18..a412cb6b1e 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -37,8 +37,9 @@ namespace CSMWorld Type_Global, Type_VerificationResults, Type_Gmsts, - Type_Gmst - + Type_Gmst, + Type_Skills, + Type_Skill }; private: From 947ab6635b3b7f038aea4ea233480bb12a2b3778 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 14:29:31 +0100 Subject: [PATCH 14/47] removed automatic detection of setting modified to the same value of base with subsequent setting modifiction state to base only (can cause problems with implicitly added records) --- apps/opencs/model/world/record.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 53bb7ea2ce..e442d0a391 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -81,9 +81,7 @@ namespace CSMWorld throw std::logic_error ("attempt to modify a deleted record"); mModified = modified; - - if (mState!=State_ModifiedOnly) - mState = mBase==mModified ? State_BaseOnly : State_Modified; + mState = State_Modified; } template From 7df0f6aaeed139d02262364ddcb9d777d0717e34 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 14:30:27 +0100 Subject: [PATCH 15/47] prepared skill record for use in editor --- components/esm/loadskil.cpp | 25 +++++++++++++++++++++++++ components/esm/loadskil.hpp | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index a4d21c5912..ac9fc27897 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -1,5 +1,7 @@ #include "loadskil.hpp" +#include + #include "esmreader.hpp" #include "esmwriter.hpp" @@ -98,6 +100,22 @@ void Skill::load(ESMReader &esm) esm.getHNT(mIndex, "INDX"); esm.getHNT(mData, "SKDT", 24); mDescription = esm.getHNOString("DESC"); + + // create an ID from the index and the name (only used in the editor and likely to change in the + // future) + std::ostringstream stream; + + stream << "#"; + + if (mIndex<10) + stream << "0"; + + stream << mIndex; + + if (mIndex>=0 && mIndex Date: Thu, 21 Mar 2013 14:31:32 +0100 Subject: [PATCH 16/47] added basic support for skills to editor --- apps/opencs/model/world/data.cpp | 6 +++++- apps/opencs/model/world/data.hpp | 2 ++ apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 1 + apps/opencs/view/world/subviews.cpp | 3 +++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 06e638b07f..6b0a83e74c 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -36,8 +36,12 @@ CSMWorld::Data::Data() mGmsts.addColumn (new VarTypeColumn (ColumnBase::Display_GmstVarType)); mGmsts.addColumn (new VarValueColumn); + mSkills.addColumn (new StringIdColumn); + mSkills.addColumn (new RecordStateColumn); + addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); + addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill); } CSMWorld::Data::~Data() @@ -102,7 +106,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) { case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break; - + case ESM::REC_SKIL: mSkills.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index e42d5c1026..dc9aee0618 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -8,6 +8,7 @@ #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -20,6 +21,7 @@ namespace CSMWorld { IdCollection mGlobals; IdCollection mGmsts; + IdCollection mSkills; std::vector mModels; std::map mModelIndex; diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 995d3ca2e2..267ddf26cc 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -86,6 +86,10 @@ void CSVDoc::View::setupWorldMenu() connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView())); world->addAction (gmsts); + QAction *skills = new QAction (tr ("Skills"), this); + connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView())); + world->addAction (skills); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -244,6 +248,11 @@ void CSVDoc::View::addGmstsSubView() addSubView (CSMWorld::UniversalId::Type_Gmsts); } +void CSVDoc::View::addSkillsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Skills); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index e91a4d4a80..4c5aa40784 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -116,6 +116,7 @@ namespace CSVDoc void addGmstsSubView(); + void addSkillsSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 351007ded5..bdff0017b4 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -14,6 +14,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Gmsts, new CSVDoc::SubViewFactoryWithCreateFlag (false)); + manager.add (CSMWorld::UniversalId::Type_Skills, + new CSVDoc::SubViewFactoryWithCreateFlag (false)); + manager.add (CSMWorld::UniversalId::Type_Global, new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file From 8e472cc62495c5a03a61f9661ae34d7a3369df94 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 Mar 2013 14:38:06 +0100 Subject: [PATCH 17/47] added description column to skill table --- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 2 ++ 2 files changed, 27 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 1492e96b7d..a84c9ddf64 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -177,6 +177,31 @@ namespace CSMWorld return true; } }; + + template + struct DescriptionColumn : public Column + { + DescriptionColumn() : Column ("Description", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mDescription.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mDescription = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 6b0a83e74c..51ea3e71be 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -39,6 +39,8 @@ CSMWorld::Data::Data() mSkills.addColumn (new StringIdColumn); mSkills.addColumn (new RecordStateColumn); + mSkills.addColumn (new DescriptionColumn); + addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill); From 3277ef26dab02aeca1668f0bf1be33cde8edb6e1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 21 Mar 2013 21:08:23 +0100 Subject: [PATCH 18/47] Fix a crash when dropping objects without a collision shape --- libs/openengine/bullet/physic.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index c4947af1e1..8641996768 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -603,6 +603,14 @@ namespace Physic btTransform trans; trans.setIdentity(); - shape->mCollisionShape->getAabb(trans, min, max); + if (shape->mRaycastingShape) + shape->mRaycastingShape->getAabb(trans, min, max); + else if (shape->mCollisionShape) + shape->mCollisionShape->getAabb(trans, min, max); + else + { + min = btVector3(0,0,0); + max = btVector3(0,0,0); + } } }} From 918cdcffc200da31602d270fac2144d8220ad937 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Mar 2013 05:50:54 +0100 Subject: [PATCH 19/47] Split up components/esm/loadlocks --- apps/esmtool/record.cpp | 8 +-- apps/esmtool/record.hpp | 2 +- apps/openmw/mwclass/lockpick.cpp | 36 ++++++------- apps/openmw/mwclass/probe.cpp | 2 +- apps/openmw/mwclass/repair.cpp | 2 +- apps/openmw/mwgui/container.cpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/tradewindow.cpp | 2 +- apps/openmw/mwscript/compilercontext.cpp | 2 +- apps/openmw/mwworld/cells.cpp | 2 +- apps/openmw/mwworld/cellstore.hpp | 2 +- apps/openmw/mwworld/containerstore.cpp | 6 +-- apps/openmw/mwworld/containerstore.hpp | 6 +-- apps/openmw/mwworld/esmstore.hpp | 4 +- apps/openmw/mwworld/manualref.hpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/CMakeLists.txt | 2 +- components/esm/loadlock.cpp | 31 +++++++++++ components/esm/loadlock.hpp | 31 +++++++++++ components/esm/loadlocks.cpp | 65 ------------------------ components/esm/loadlocks.hpp | 56 -------------------- components/esm/loadprob.cpp | 30 +++++++++++ components/esm/loadprob.hpp | 31 +++++++++++ components/esm/loadrepa.cpp | 31 +++++++++++ components/esm/loadrepa.hpp | 31 +++++++++++ components/esm/records.hpp | 4 +- 26 files changed, 228 insertions(+), 166 deletions(-) create mode 100644 components/esm/loadlock.cpp create mode 100644 components/esm/loadlock.hpp delete mode 100644 components/esm/loadlocks.cpp delete mode 100644 components/esm/loadlocks.hpp create mode 100644 components/esm/loadprob.cpp create mode 100644 components/esm/loadprob.hpp create mode 100644 components/esm/loadrepa.cpp create mode 100644 components/esm/loadrepa.hpp diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 38fddd6b92..de3a175106 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -275,7 +275,7 @@ RecordBase::create(ESM::NAME type) } case ESM::REC_LOCK: { - record = new EsmTool::Record; + record = new EsmTool::Record; break; } case ESM::REC_LTEX: @@ -864,14 +864,13 @@ void Record::print() } template<> -void Record::print() +void Record::print() { std::cout << " Name: " << mData.mName << std::endl; std::cout << " Model: " << mData.mModel << std::endl; std::cout << " Icon: " << mData.mIcon << std::endl; if (mData.mScript != "") std::cout << " Script: " << mData.mScript << std::endl; - std::cout << " Type: " << mData.mType << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl; @@ -886,8 +885,6 @@ void Record::print() std::cout << " Icon: " << mData.mIcon << std::endl; if (mData.mScript != "") std::cout << " Script: " << mData.mScript << std::endl; - // BUG? No Type Label? - std::cout << " Type: " << mData.mType << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl; @@ -902,7 +899,6 @@ void Record::print() std::cout << " Icon: " << mData.mIcon << std::endl; if (mData.mScript != "") std::cout << " Script: " << mData.mScript << std::endl; - std::cout << " Type: " << mData.mType << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl; diff --git a/apps/esmtool/record.hpp b/apps/esmtool/record.hpp index c3daa9d0c3..e0dd988a65 100644 --- a/apps/esmtool/record.hpp +++ b/apps/esmtool/record.hpp @@ -104,7 +104,7 @@ namespace EsmTool template<> void Record::print(); template<> void Record::print(); template<> void Record::print(); - template<> void Record::print(); + template<> void Record::print(); template<> void Record::print(); template<> void Record::print(); template<> void Record::print(); diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 665644736d..6fa8f55520 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -1,7 +1,7 @@ #include "lockpick.hpp" -#include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -41,8 +41,8 @@ namespace MWClass std::string Lockpick::getModel(const MWWorld::Ptr &ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); assert(ref->mBase != NULL); const std::string &model = ref->mBase->mModel; @@ -54,8 +54,8 @@ namespace MWClass std::string Lockpick::getName (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return ref->mBase->mName; } @@ -75,8 +75,8 @@ namespace MWClass std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return ref->mBase->mScript; } @@ -92,8 +92,8 @@ namespace MWClass int Lockpick::getValue (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return ref->mBase->mData.mValue; } @@ -102,7 +102,7 @@ namespace MWClass { boost::shared_ptr instance (new Lockpick); - registerClass (typeid (ESM::Tool).name(), instance); + registerClass (typeid (ESM::Lockpick).name(), instance); } std::string Lockpick::getUpSoundId (const MWWorld::Ptr& ptr) const @@ -117,24 +117,24 @@ namespace MWClass std::string Lockpick::getInventoryIcon (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return ref->mBase->mIcon; } bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return (ref->mBase->mName != ""); } MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); MWGui::ToolTipInfo info; info.caption = ref->mBase->mName + MWGui::ToolTips::getCountString(ptr.getRefData().getCount()); @@ -171,8 +171,8 @@ namespace MWClass MWWorld::Ptr Lockpick::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = + ptr.get(); return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell); } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 5b1b55bd31..68d9b49c30 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -1,7 +1,7 @@ #include "probe.hpp" -#include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index d6afe93198..8a13aa2078 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -1,7 +1,7 @@ #include "repair.hpp" -#include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index e476865433..9c1fbae69e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -45,7 +45,7 @@ namespace mapping.push_back( typeid(ESM::Book).name() ); mapping.push_back( typeid(ESM::Light).name() ); mapping.push_back( typeid(ESM::Miscellaneous).name() ); - mapping.push_back( typeid(ESM::Tool).name() ); + mapping.push_back( typeid(ESM::Lockpick).name() ); mapping.push_back( typeid(ESM::Repair).name() ); mapping.push_back( typeid(ESM::Probe).name() ); diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 29966bd08a..578ec3da3e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -308,7 +308,7 @@ namespace MWGui && (type != typeid(ESM::Ingredient).name()) && (type != typeid(ESM::Light).name()) && (type != typeid(ESM::Miscellaneous).name()) - && (type != typeid(ESM::Tool).name()) + && (type != typeid(ESM::Lockpick).name()) && (type != typeid(ESM::Probe).name()) && (type != typeid(ESM::Repair).name()) && (type != typeid(ESM::Weapon).name()) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 0fd24601a8..f84a0abc88 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -368,7 +368,7 @@ namespace MWGui return services & ESM::NPC::Books; else if (item.getTypeName() == typeid(ESM::Ingredient).name()) return services & ESM::NPC::Ingredients; - else if (item.getTypeName() == typeid(ESM::Tool).name()) + else if (item.getTypeName() == typeid(ESM::Lockpick).name()) return services & ESM::NPC::Picks; else if (item.getTypeName() == typeid(ESM::Probe).name()) return services & ESM::NPC::Probes; diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 57d93512f4..7e63a33b25 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -59,7 +59,7 @@ namespace MWScript store.get().search (name) || store.get().search (name) || store.get().search (name) || - store.get().search (name) || + store.get().search (name) || store.get().search (name) || store.get().search (name) || store.get().search (name) || diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index f95d30df13..5f771be475 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -206,7 +206,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce if (MWWorld::LiveCellRef *ref = cell.mLights.find (name)) ptr = Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = cell.mLockpicks.find (name)) + if (MWWorld::LiveCellRef *ref = cell.mLockpicks.find (name)) ptr = Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = cell.mMiscItems.find (name)) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index c182f196bc..2e6b45bb7e 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -112,7 +112,7 @@ namespace MWWorld CellRefList mCreatureLists; CellRefList mItemLists; CellRefList mLights; - CellRefList mLockpicks; + CellRefList mLockpicks; CellRefList mMiscItems; CellRefList mNpcs; CellRefList mProbes; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 8a7884e9e0..3dce049f4d 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -171,7 +171,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr case Type_Clothing: clothes.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --clothes.mList.end()); break; case Type_Ingredient: ingreds.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --ingreds.mList.end()); break; case Type_Light: lights.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lights.mList.end()); break; - case Type_Lockpick: lockpicks.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break; + case Type_Lockpick: lockpicks.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break; case Type_Miscellaneous: miscItems.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --miscItems.mList.end()); break; case Type_Probe: probes.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --probes.mList.end()); break; case Type_Repair: repairs.mList.push_back (*ptr.get()); it = ContainerStoreIterator(this, --repairs.mList.end()); break; @@ -272,7 +272,7 @@ int MWWorld::ContainerStore::getType (const Ptr& ptr) if (ptr.getTypeName()==typeid (ESM::Light).name()) return Type_Light; - if (ptr.getTypeName()==typeid (ESM::Tool).name()) + if (ptr.getTypeName()==typeid (ESM::Lockpick).name()) return Type_Lockpick; if (ptr.getTypeName()==typeid (ESM::Miscellaneous).name()) @@ -321,7 +321,7 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *contain : mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){} MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){} MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){} diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index e4f75d5478..9d315d27f0 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -44,7 +44,7 @@ namespace MWWorld MWWorld::CellRefList clothes; MWWorld::CellRefList ingreds; MWWorld::CellRefList lights; - MWWorld::CellRefList lockpicks; + MWWorld::CellRefList lockpicks; MWWorld::CellRefList miscItems; MWWorld::CellRefList probes; MWWorld::CellRefList repairs; @@ -127,7 +127,7 @@ namespace MWWorld MWWorld::CellRefList::List::iterator mClothing; MWWorld::CellRefList::List::iterator mIngredient; MWWorld::CellRefList::List::iterator mLight; - MWWorld::CellRefList::List::iterator mLockpick; + MWWorld::CellRefList::List::iterator mLockpick; MWWorld::CellRefList::List::iterator mMiscellaneous; MWWorld::CellRefList::List::iterator mProbe; MWWorld::CellRefList::List::iterator mRepair; @@ -149,7 +149,7 @@ namespace MWWorld ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index b9b95e4f4e..61a106e163 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -32,7 +32,7 @@ namespace MWWorld Store mCreatureLists; Store mItemLists; Store mLights; - Store mLockpicks; + Store mLockpicks; Store mMiscItems; Store mNpcs; Store mNpcChange; @@ -312,7 +312,7 @@ namespace MWWorld } template <> - inline const Store &ESMStore::get() const { + inline const Store &ESMStore::get() const { return mLockpicks; } diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 91b8cf8cd4..466341b953 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -53,7 +53,7 @@ namespace MWWorld !create (store.get(), name) && !create (store.get(), name) && !create (store.get(), name) && - !create (store.get(), name) && + !create (store.get(), name) && !create (store.get(), name) && !create (store.get(), name) && !create (store.get(), name) && diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1b5dc3bd35..5d6863c029 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -101,7 +101,7 @@ namespace MWWorld return Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mLights)) return Ptr (ref, &cell); - if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mLockpicks)) + if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mLockpicks)) return Ptr (ref, &cell); if (MWWorld::LiveCellRef *ref = searchViaHandle (handle, cell.mMiscItems)) return Ptr (ref, &cell); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index f7b97056cb..88bf764445 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -37,7 +37,7 @@ add_component_dir (file_finder add_component_dir (esm attr defs esmcommon esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst - loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc + loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 ) diff --git a/components/esm/loadlock.cpp b/components/esm/loadlock.cpp new file mode 100644 index 0000000000..02a36abfe6 --- /dev/null +++ b/components/esm/loadlock.cpp @@ -0,0 +1,31 @@ +#include "loadlock.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + +void Lockpick::load(ESMReader &esm) +{ + mModel = esm.getHNString("MODL"); + mName = esm.getHNString("FNAM"); + + esm.getHNT(mData, "LKDT", 16); + + mScript = esm.getHNOString("SCRI"); + mIcon = esm.getHNOString("ITEX"); +} + +void Lockpick::save(ESMWriter &esm) +{ + esm.writeHNCString("MODL", mModel); + esm.writeHNCString("FNAM", mName); + + esm.writeHNT("LKDT", mData, 16); + esm.writeHNOString("SCRI", mScript); + esm.writeHNOCString("ITEX", mIcon); +} + + +} diff --git a/components/esm/loadlock.hpp b/components/esm/loadlock.hpp new file mode 100644 index 0000000000..0bbedf362f --- /dev/null +++ b/components/esm/loadlock.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_ESM_LOCK_H +#define OPENMW_ESM_LOCK_H + +#include + +namespace ESM +{ + +class ESMReader; +class ESMWriter; + +struct Lockpick +{ + struct Data + { + float mWeight; + int mValue; + + float mQuality; + int mUses; + }; // Size = 16 + + Data mData; + std::string mId, mName, mModel, mIcon, mScript; + + void load(ESMReader &esm); + void save(ESMWriter &esm); +}; + +} +#endif diff --git a/components/esm/loadlocks.cpp b/components/esm/loadlocks.cpp deleted file mode 100644 index 057da595e7..0000000000 --- a/components/esm/loadlocks.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "loadlocks.hpp" - -#include "esmreader.hpp" -#include "esmwriter.hpp" - -namespace ESM -{ - -void Tool::load(ESMReader &esm) -{ - mModel = esm.getHNString("MODL"); - mName = esm.getHNString("FNAM"); - - esm.getSubName(); - NAME n = esm.retSubName(); - // The data name varies, RIDT for repair items, LKDT for lock - // picks, PBDT for probes - - esm.getHT(mData, 16); - - if (n == "RIDT") - { - mType = Type_Repair; - // Swap t.data.quality and t.data.uses for repair items (sigh) - float tmp = *((float*) &mData.mUses); - mData.mUses = *((int*) &mData.mQuality); - mData.mQuality = tmp; - } - else if (n == "LKDT") - mType = Type_Pick; - else if (n == "PBDT") - mType = Type_Probe; - - mScript = esm.getHNOString("SCRI"); - mIcon = esm.getHNOString("ITEX"); -} - -void Tool::save(ESMWriter &esm) -{ - esm.writeHNCString("MODL", mModel); - esm.writeHNCString("FNAM", mName); - - std::string typeName; - switch(mType) - { - case Type_Repair: typeName = "RIDT"; break; - case Type_Pick: typeName = "LKDT"; break; - case Type_Probe: typeName = "PBDT"; break; - } - - Data write = mData; - if (mType == Type_Repair) - { - float tmp = *((float*) &write.mUses); - write.mUses = *((int*) &write.mQuality); - write.mQuality = tmp; - } - - esm.writeHNT(typeName, write, 16); - esm.writeHNOString("SCRI", mScript); - esm.writeHNOCString("ITEX", mIcon); -} - - -} diff --git a/components/esm/loadlocks.hpp b/components/esm/loadlocks.hpp deleted file mode 100644 index 8e88c548e7..0000000000 --- a/components/esm/loadlocks.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef OPENMW_ESM_LOCKS_H -#define OPENMW_ESM_LOCKS_H - -#include - -namespace ESM -{ - -class ESMReader; -class ESMWriter; - -/* - * This file covers lockpicks (LOCK), probes (PROB) and armor repair - * items (REPA). These have nearly identical data structures. - */ - -struct Tool -{ - enum Type - { - Type_Pick, - Type_Probe, - Type_Repair - }; - - struct Data - { - float mWeight; - int mValue; - - float mQuality; // And when I say nearly identical structure, I - int mUses; // mean perfectly identical except that these two - // variables are swaped for repair items. Don't ask - // me why. - }; // Size = 16 - - Data mData; - Type mType; - std::string mId, mName, mModel, mIcon, mScript; - - void load(ESMReader &esm); - void save(ESMWriter &esm); -}; - -struct Probe: Tool -{ - Probe() { mType = Type_Probe; } -}; - -struct Repair: Tool -{ - Repair() { mType = Type_Repair; } -}; - -} -#endif diff --git a/components/esm/loadprob.cpp b/components/esm/loadprob.cpp new file mode 100644 index 0000000000..bbaec1ce2d --- /dev/null +++ b/components/esm/loadprob.cpp @@ -0,0 +1,30 @@ +#include "loadprob.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + +void Probe::load(ESMReader &esm) +{ + mModel = esm.getHNString("MODL"); + mName = esm.getHNString("FNAM"); + + esm.getHNT(mData, "PBDT", 16); + + mScript = esm.getHNOString("SCRI"); + mIcon = esm.getHNOString("ITEX"); +} + +void Probe::save(ESMWriter &esm) +{ + esm.writeHNCString("MODL", mModel); + esm.writeHNCString("FNAM", mName); + + esm.writeHNT("PBDT", mData, 16); + esm.writeHNOString("SCRI", mScript); + esm.writeHNOCString("ITEX", mIcon); +} + +} diff --git a/components/esm/loadprob.hpp b/components/esm/loadprob.hpp new file mode 100644 index 0000000000..4a47a86005 --- /dev/null +++ b/components/esm/loadprob.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_ESM_PROBE_H +#define OPENMW_ESM_PROBE_H + +#include + +namespace ESM +{ + +class ESMReader; +class ESMWriter; + +struct Probe +{ + struct Data + { + float mWeight; + int mValue; + + float mQuality; + int mUses; + }; // Size = 16 + + Data mData; + std::string mId, mName, mModel, mIcon, mScript; + + void load(ESMReader &esm); + void save(ESMWriter &esm); +}; + +} +#endif diff --git a/components/esm/loadrepa.cpp b/components/esm/loadrepa.cpp new file mode 100644 index 0000000000..f7eeddf961 --- /dev/null +++ b/components/esm/loadrepa.cpp @@ -0,0 +1,31 @@ +#include "loadrepa.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" + +namespace ESM +{ + +void Repair::load(ESMReader &esm) +{ + mModel = esm.getHNString("MODL"); + mName = esm.getHNString("FNAM"); + + esm.getHNT(mData, "RIDT", 16); + + mScript = esm.getHNOString("SCRI"); + mIcon = esm.getHNOString("ITEX"); +} + +void Repair::save(ESMWriter &esm) +{ + esm.writeHNCString("MODL", mModel); + esm.writeHNCString("FNAM", mName); + + esm.writeHNT("RIDT", mData, 16); + esm.writeHNOString("SCRI", mScript); + esm.writeHNOCString("ITEX", mIcon); +} + + +} diff --git a/components/esm/loadrepa.hpp b/components/esm/loadrepa.hpp new file mode 100644 index 0000000000..60ff5df905 --- /dev/null +++ b/components/esm/loadrepa.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_ESM_REPA_H +#define OPENMW_ESM_REPA_H + +#include + +namespace ESM +{ + +class ESMReader; +class ESMWriter; + +struct Repair +{ + struct Data + { + float mWeight; + int mValue; + + int mUses; + float mQuality; + }; // Size = 16 + + Data mData; + std::string mId, mName, mModel, mIcon, mScript; + + void load(ESMReader &esm); + void save(ESMWriter &esm); +}; + +} +#endif diff --git a/components/esm/records.hpp b/components/esm/records.hpp index 0662c797c1..7a0452eb3f 100644 --- a/components/esm/records.hpp +++ b/components/esm/records.hpp @@ -26,7 +26,9 @@ #include "loadland.hpp" #include "loadlevlist.hpp" #include "loadligh.hpp" -#include "loadlocks.hpp" +#include "loadlock.hpp" +#include "loadrepa.hpp" +#include "loadprob.hpp" #include "loadltex.hpp" #include "loadmgef.hpp" #include "loadmisc.hpp" From feaf2b43fbfc7f3c2b3e6b7af859db1dc45b6d4d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 22 Mar 2013 09:44:59 +0100 Subject: [PATCH 20/47] disabled and deleted objects where not correctly ignored during adding objects to a cell when it became active --- apps/openmw/mwworld/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 592fb5c80a..339026ca60 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -41,7 +41,7 @@ namespace ++current; - if (it->mData.getCount() || it->mData.isEnabled()) + if (it->mData.getCount() && it->mData.isEnabled()) { MWWorld::Ptr ptr (&*it, &cell); From 8e2f9f5186b6a969c8d73c255bdac7a28cef5ebe Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Mar 2013 12:24:09 +0100 Subject: [PATCH 21/47] Fix CellRef to load current weapon/armor health correctly, also show it in the tooltips --- apps/esmtool/esmtool.cpp | 2 +- apps/openmw/mwclass/armor.cpp | 5 +++-- apps/openmw/mwclass/lockpick.cpp | 4 ++-- apps/openmw/mwclass/probe.cpp | 4 ++-- apps/openmw/mwclass/repair.cpp | 4 ++-- apps/openmw/mwclass/weapon.cpp | 7 +++++-- apps/openmw/mwworld/manualref.hpp | 3 +-- components/esm/loadcell.cpp | 17 +++++------------ components/esm/loadcell.hpp | 12 ++++-------- 9 files changed, 25 insertions(+), 33 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 20c01af259..521383f3ff 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -227,7 +227,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) std::cout << " Refnum: " << ref.mRefnum << std::endl; std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " Owner: '" << ref.mOwner << "'\n"; - std::cout << " INTV: " << ref.mIntv << " NAM9: " << ref.mIntv << std::endl; + std::cout << " Uses/health: " << ref.mCharge << " NAM9: " << ref.mNam9 << std::endl; } } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index fdf211c28a..513ebf75fc 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -247,8 +247,9 @@ namespace MWClass text += "\n#{sArmorRating}: " + MWGui::ToolTips::toString(ref->mBase->mData.mArmor); - /// \todo store the current armor health somewhere - text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); + int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth; + text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" + + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight) + " (" + typeText + ")"; text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 6fa8f55520..2015726968 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -142,9 +142,9 @@ namespace MWClass std::string text; - /// \todo store remaining uses somewhere + int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 68d9b49c30..e4533af655 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -141,9 +141,9 @@ namespace MWClass std::string text; - /// \todo store remaining uses somewhere + int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 8a13aa2078..f0b6fe88d9 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -131,9 +131,9 @@ namespace MWClass std::string text; - /// \todo store remaining uses somewhere + int remainingUses = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mUses; - text += "\n#{sUses}: " + MWGui::ToolTips::toString(ref->mBase->mData.mUses); + text += "\n#{sUses}: " + MWGui::ToolTips::toString(remainingUses); text += "\n#{sQuality}: " + MWGui::ToolTips::toString(ref->mBase->mData.mQuality); text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 475c08ccbf..e9e42d3fdd 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -334,9 +334,12 @@ namespace MWClass } } - /// \todo store the current weapon health somewhere if (ref->mBase->mData.mType < 11) // thrown weapons and arrows/bolts don't have health, only quantity - text += "\n#{sCondition}: " + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); + { + int remainingHealth = (ptr.getCellRef().mCharge != -1) ? ptr.getCellRef().mCharge : ref->mBase->mData.mHealth; + text += "\n#{sCondition}: " + MWGui::ToolTips::toString(remainingHealth) + "/" + + MWGui::ToolTips::toString(ref->mBase->mData.mHealth); + } text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 466341b953..58395d8798 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -68,8 +68,7 @@ namespace MWWorld cellRef.mRefnum = -1; cellRef.mScale = 1; cellRef.mFactIndex = 0; - cellRef.mCharge = 0; - cellRef.mIntv = 0; + cellRef.mCharge = -1; cellRef.mNam9 = 0; cellRef.mTeleport = false; cellRef.mLockLevel = 0; diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index da60f76af8..0731a8ff80 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -14,7 +14,7 @@ namespace ESM { -/// Some overloaded copare operators. +/// Some overloaded compare operators. bool operator==(const MovedCellRef& ref, int pRefnum) { return (ref.mRefnum == pRefnum); @@ -43,13 +43,9 @@ void CellRef::save(ESMWriter &esm) esm.writeHNT("INDX", mFactIndex); } - if (mCharge != -1.0) { - esm.writeHNT("XCHG", mCharge); - } + if (mCharge != -1) + esm.writeHNT("INTV", mCharge); - if (mIntv != -1) { - esm.writeHNT("INTV", mIntv); - } if (mNam9 != 0) { esm.writeHNT("NAM9", mNam9); } @@ -285,12 +281,9 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) ref.mFactIndex = -2; esm.getHNOT(ref.mFactIndex, "INDX"); - ref.mCharge = -1.0; - esm.getHNOT(ref.mCharge, "XCHG"); - - ref.mIntv = -1; ref.mNam9 = 0; - esm.getHNOT(ref.mIntv, "INTV"); + ref.mCharge = -1; + esm.getHNOT(ref.mCharge, "INTV"); esm.getHNOT(ref.mNam9, "NAM9"); // Present for doors that teleport you to another cell. diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 7db6dbe77c..97aa86ba0f 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -52,15 +52,11 @@ public: // is -1, which I assume means "any rank". int mFactIndex; - // Depends on context - possibly weapon health, number of uses left - // or weapon magic charge? - float mCharge; + // For weapon or armor, this is the remaining item health. + // For tools (lockpicks, probes, repair hammer) it is the remaining uses. + int mCharge; - // I have no idea, these are present some times, often along with - // owner (ANAM) and sometimes otherwise. They are often (but not - // always) 1. INTV is big for lights (possibly a float?), might have - // something to do with remaining light "charge". - int mIntv, mNam9; + int mNam9; // For doors - true if this door teleports to somewhere else, false // if it should open through animation. From 20774f8f8178ad6a4ee9aea47da09ae0f7b075b4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Mar 2013 14:13:10 +0100 Subject: [PATCH 22/47] Added merchant repair feature --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 3 + apps/openmw/mwgui/dialogue.cpp | 8 ++ apps/openmw/mwgui/dialogue.hpp | 3 +- apps/openmw/mwgui/merchantrepair.cpp | 132 ++++++++++++++++++ apps/openmw/mwgui/merchantrepair.hpp | 37 +++++ apps/openmw/mwgui/mode.hpp | 2 + apps/openmw/mwgui/spellbuyingwindow.cpp | 11 -- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 - apps/openmw/mwgui/windowmanagerimp.cpp | 13 ++ apps/openmw/mwgui/windowmanagerimp.hpp | 4 + apps/openmw/mwworld/containerstore.cpp | 4 +- files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_merchantrepair.layout | 33 +++++ files/mygui/openmw_spell_buying_window.layout | 10 +- 16 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 apps/openmw/mwgui/merchantrepair.cpp create mode 100644 apps/openmw/mwgui/merchantrepair.hpp create mode 100644 files/mygui/openmw_merchantrepair.layout diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0edc18afba..11c6360e57 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -31,6 +31,7 @@ add_openmw_dir (mwgui confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons + merchantrepair ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index cd28bb47e7..0a6de5e14d 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -238,6 +238,7 @@ namespace MWBase virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; + virtual void startRepair(MWWorld::Ptr actor) = 0; virtual void changePointer (const std::string& name) = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 1628199950..b75c514a29 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -367,6 +367,9 @@ namespace MWDialogue if (services & ESM::NPC::Enchanting) windowServices |= MWGui::DialogueWindow::Service_Enchant; + if (services & ESM::NPC::Repair) + windowServices |= MWGui::DialogueWindow::Service_Repair; + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->setServices (windowServices); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0bbf7c7af4..9a7e51874f 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -280,6 +280,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id) mWindowManager.pushGuiMode(GM_Training); mWindowManager.startTraining (mPtr); } + else if (topic == gmst.find("sRepair")->getString()) + { + mWindowManager.pushGuiMode(GM_MerchantRepair); + mWindowManager.startRepair (mPtr); + } } } } @@ -327,6 +332,9 @@ void DialogueWindow::setKeywords(std::list keyWords) if (mServices & Service_Training) mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString()); + if (mServices & Service_Repair) + mTopicsList->addItem(gmst.find("sRepair")->getString()); + if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name()) mTopicsList->addSeparator(); diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index a8e0a6d174..187731fc77 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -81,7 +81,8 @@ namespace MWGui Service_CreateSpells = 0x04, Service_Enchant = 0x08, Service_Training = 0x10, - Service_Travel = 0x20 + Service_Travel = 0x20, + Service_Repair = 0x40 }; protected: diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp new file mode 100644 index 0000000000..0a65326050 --- /dev/null +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -0,0 +1,132 @@ +#include "merchantrepair.hpp" + +#include + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/class.hpp" + +#include "list.hpp" +#include "inventorywindow.hpp" +#include "tradewindow.hpp" + +namespace MWGui +{ + +MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager) + : WindowBase("openmw_merchantrepair.layout", parWindowManager) +{ + getWidget(mList, "RepairView"); + getWidget(mOkButton, "OkButton"); + getWidget(mGoldLabel, "PlayerGold"); + + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick); +} + +void MerchantRepair::startRepair(const MWWorld::Ptr &actor) +{ + mActor = actor; + + while (mList->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0)); + + int currentY = 0; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + for (MWWorld::ContainerStoreIterator iter (store.begin()); + iter!=store.end(); ++iter) + { + if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) + { + int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter); + int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; + if (maxDurability == durability) + continue; + + int basePrice = MWWorld::Class::get(*iter).getValue(*iter); + float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get() + .find("fRepairMult")->getFloat(); + + float p = std::max(1, basePrice); + float r = std::max(1, static_cast(maxDurability / p)); + + int x = ((maxDurability - durability) / r); + x = (fRepairMult * x); + + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); + + + std::string name = MWWorld::Class::get(*iter).getName(*iter) + + " - " + boost::lexical_cast(price) + + MWBase::Environment::get().getWorld()->getStore().get() + .find("sgp")->getString();; + + + MyGUI::Button* button = + mList->createWidget( + (price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", + 0, + currentY, + 0, + 18, + MyGUI::Align::Default + ); + + currentY += 18; + + button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold()); + button->setUserString("Price", boost::lexical_cast(price)); + button->setUserData(*iter); + button->setCaptionWithReplacing(name); + button->setSize(button->getTextSize().width,18); + button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel); + button->setUserString("ToolTipType", "ItemPtr"); + button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick); + } + } + mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY))); + + mGoldLabel->setCaptionWithReplacing("#{sGold}: " + + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); +} + +void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (mList->getViewOffset().top + _rel*0.3 > 0) + mList->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3)); +} + +void MerchantRepair::open() +{ + center(); +} + +void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) +{ + // repair + MWWorld::Ptr item = *sender->getUserData(); + item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item); + + MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); + + int price = boost::lexical_cast(sender->getUserString("Price")); + mWindowManager.getTradeWindow()->addOrRemoveGold(-price); + + startRepair(mActor); +} + +void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender) +{ + mWindowManager.removeGuiMode(GM_MerchantRepair); +} + +} diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp new file mode 100644 index 0000000000..4b7e2b8fbd --- /dev/null +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -0,0 +1,37 @@ +#ifndef OPENMW_MWGUI_MERCHANTREPAIR_H +#define OPENMW_MWGUI_MERCHANTREPAIR_H + +#include "window_base.hpp" +#include "../mwworld/ptr.hpp" + + + +namespace MWGui +{ + +class MerchantRepair : public WindowBase +{ +public: + MerchantRepair(MWBase::WindowManager &parWindowManager); + + virtual void open(); + + void startRepair(const MWWorld::Ptr& actor); + +private: + MyGUI::ScrollView* mList; + MyGUI::Button* mOkButton; + MyGUI::TextBox* mGoldLabel; + + MWWorld::Ptr mActor; + +protected: + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onRepairButtonClick(MyGUI::Widget* sender); + void onOkButtonClick(MyGUI::Widget* sender); + +}; + +} + +#endif diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 3195372978..4091f47acc 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -16,6 +16,7 @@ namespace MWGui GM_Scroll, // Read scroll GM_Book, // Read book GM_Alchemy, // Make potions + GM_Repair, GM_Dialogue, // NPC interaction GM_Barter, @@ -26,6 +27,7 @@ namespace MWGui GM_SpellCreation, GM_Enchanting, GM_Training, + GM_MerchantRepair, GM_Levelup, diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 40fcf2988a..d39ad6a5ae 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -32,20 +32,9 @@ namespace MWGui getWidget(mCancelButton, "CancelButton"); getWidget(mPlayerGold, "PlayerGold"); - getWidget(mSelect, "Select"); - getWidget(mSpells, "Spells"); getWidget(mSpellsView, "SpellsView"); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked); - - mSpells->setCoord(450/2-mSpells->getTextSize().width/2, - mSpells->getTop(), - mSpells->getTextSize().width, - mSpells->getHeight()); - mSelect->setCoord(8, - mSelect->getTop(), - mSelect->getTextSize().width, - mSelect->getHeight()); } void SpellBuyingWindow::addSpell(const std::string& spellId) diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index c4988fff35..f9cda35df0 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -28,8 +28,6 @@ namespace MWGui protected: MyGUI::Button* mCancelButton; MyGUI::TextBox* mPlayerGold; - MyGUI::TextBox* mSpells; - MyGUI::TextBox* mSelect; MyGUI::ScrollView* mSpellsView; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b7d6ed1c9b..07ea726206 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -55,6 +55,7 @@ #include "exposedwindow.hpp" #include "cursor.hpp" #include "spellicons.hpp" +#include "merchantrepair.hpp" using namespace MWGui; @@ -90,6 +91,7 @@ WindowManager::WindowManager( , mSpellCreationDialog(NULL) , mEnchantingDialog(NULL) , mTrainingWindow(NULL) + , mMerchantRepair(NULL) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -180,6 +182,7 @@ WindowManager::WindowManager( mSpellCreationDialog = new SpellCreationDialog(*this); mEnchantingDialog = new EnchantingDialog(*this); mTrainingWindow = new TrainingWindow(*this); + mMerchantRepair = new MerchantRepair(*this); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -245,6 +248,7 @@ WindowManager::~WindowManager() delete mTrainingWindow; delete mCountDialog; delete mQuickKeysMenu; + delete mMerchantRepair; delete mCursor; cleanupGarbage(); @@ -303,6 +307,7 @@ void WindowManager::updateVisible() mSpellCreationDialog->setVisible(false); mEnchantingDialog->setVisible(false); mTrainingWindow->setVisible(false); + mMerchantRepair->setVisible(false); mHud->setVisible(mHudEnabled); @@ -428,6 +433,9 @@ void WindowManager::updateVisible() case GM_Training: mTrainingWindow->setVisible(true); break; + case GM_MerchantRepair: + mMerchantRepair->setVisible(true); + break; case GM_InterMessageBox: break; case GM_Journal: @@ -1132,6 +1140,11 @@ void WindowManager::startTraining(MWWorld::Ptr actor) mTrainingWindow->startTraining(actor); } +void WindowManager::startRepair(MWWorld::Ptr actor) +{ + mMerchantRepair->startRepair(actor); +} + const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a7baf5207e..2242a8467b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -74,6 +74,7 @@ namespace MWGui class TrainingWindow; class Cursor; class SpellIcons; + class MerchantRepair; class WindowManager : public MWBase::WindowManager { @@ -229,6 +230,7 @@ namespace MWGui virtual void startSpellMaking(MWWorld::Ptr actor); virtual void startEnchanting(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor); + virtual void startRepair(MWWorld::Ptr actor); virtual void changePointer (const std::string& name); @@ -266,6 +268,8 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; + MerchantRepair* mMerchantRepair; + Translation::Storage& mTranslationDataStorage; Cursor* mCursor; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 3dce049f4d..223514e086 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -62,13 +62,13 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { - /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented + /// \todo add current enchantment charge here when it is implemented if ( ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier) && ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner && ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul - && ptr1.mCellRef->mCharge == ptr2.mCellRef->mCharge) + && ptr1.mCellRef->mCharge == -1) // item that is already partly used up never stacks return true; return false; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index beace5b81e..4adebf1dfd 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -78,6 +78,7 @@ set(MYGUI_FILES openmw_trainingwindow.layout openmw_travel_window.layout openmw_persuasion_dialog.layout + openmw_merchantrepair.layout smallbars.png DejaVuLGCSansMono.ttf markers.png diff --git a/files/mygui/openmw_merchantrepair.layout b/files/mygui/openmw_merchantrepair.layout new file mode 100644 index 0000000000..360f5f4f09 --- /dev/null +++ b/files/mygui/openmw_merchantrepair.layout @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_spell_buying_window.layout b/files/mygui/openmw_spell_buying_window.layout index 1e18fda236..c55cd0e22d 100644 --- a/files/mygui/openmw_spell_buying_window.layout +++ b/files/mygui/openmw_spell_buying_window.layout @@ -5,13 +5,13 @@ - - + + - - - + + + From 78f3f19f62393d5d256657b8aa8c60e1eb94058a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Mar 2013 14:28:50 +0100 Subject: [PATCH 23/47] Thrown weapons, arrows and bolts shouldn't have item health --- apps/openmw/mwclass/weapon.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index e9e42d3fdd..a6a8e631b3 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -75,7 +75,10 @@ namespace MWClass bool Weapon::hasItemHealth (const MWWorld::Ptr& ptr) const { - return true; + MWWorld::LiveCellRef *ref = + ptr.get(); + + return (ref->mBase->mData.mType < 11); // thrown weapons and arrows/bolts don't have health, only quantity } int Weapon::getItemMaxHealth (const MWWorld::Ptr& ptr) const From a2ca679beb294140710a5dd1b0e2b273405db8a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Mar 2013 08:16:46 +0100 Subject: [PATCH 24/47] Added PC repair feature --- apps/openmw/CMakeLists.txt | 6 +- apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwclass/repair.cpp | 19 +++ apps/openmw/mwclass/repair.hpp | 12 ++ apps/openmw/mwgui/repair.cpp | 157 +++++++++++++++++++++++++ apps/openmw/mwgui/repair.hpp | 46 ++++++++ apps/openmw/mwgui/windowmanagerimp.cpp | 13 ++ apps/openmw/mwgui/windowmanagerimp.hpp | 3 + apps/openmw/mwmechanics/repair.cpp | 110 +++++++++++++++++ apps/openmw/mwmechanics/repair.hpp | 23 ++++ apps/openmw/mwworld/actionrepair.cpp | 18 +++ apps/openmw/mwworld/actionrepair.hpp | 17 +++ apps/openmw/mwworld/containerstore.cpp | 24 ++-- files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_repair.layout | 33 ++++++ files/mygui/openmw_text.skin.xml | 4 +- 16 files changed, 469 insertions(+), 18 deletions(-) create mode 100644 apps/openmw/mwgui/repair.cpp create mode 100644 apps/openmw/mwgui/repair.hpp create mode 100644 apps/openmw/mwmechanics/repair.cpp create mode 100644 apps/openmw/mwmechanics/repair.hpp create mode 100644 apps/openmw/mwworld/actionrepair.cpp create mode 100644 apps/openmw/mwworld/actionrepair.hpp create mode 100644 files/mygui/openmw_repair.layout diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 11c6360e57..41599b35db 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -31,7 +31,7 @@ add_openmw_dir (mwgui confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons - merchantrepair + merchantrepair repair ) add_openmw_dir (mwdialogue @@ -54,7 +54,7 @@ add_openmw_dir (mwworld containerstore actiontalk actiontake manualref player cellfunctors failedaction cells localscripts customdata weather inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat - esmstore store recordcmp fallback + esmstore store recordcmp fallback actionrepair ) add_openmw_dir (mwclass @@ -65,7 +65,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow - aiescort aiactivate + aiescort aiactivate repair ) add_openmw_dir (mwbase diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 0a6de5e14d..6760c89d07 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -239,6 +239,7 @@ namespace MWBase virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; virtual void startRepair(MWWorld::Ptr actor) = 0; + virtual void startRepairItem(MWWorld::Ptr item) = 0; virtual void changePointer (const std::string& name) = 0; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index f0b6fe88d9..bafedee88b 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -12,6 +12,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/actionrepair.hpp" #include "../mwgui/tooltips.hpp" @@ -120,6 +121,19 @@ namespace MWClass return (ref->mBase->mName != ""); } + bool Repair::hasItemHealth (const MWWorld::Ptr& ptr) const + { + return true; + } + + int Repair::getItemMaxHealth (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mData.mUses; + } + MWGui::ToolTipInfo Repair::getToolTipInfo (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = @@ -156,4 +170,9 @@ namespace MWClass return MWWorld::Ptr(&cell.mRepairs.insert(*ref), &cell); } + + boost::shared_ptr Repair::use (const MWWorld::Ptr& ptr) const + { + return boost::shared_ptr(new MWWorld::ActionRepair(ptr)); + } } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index c58e38f96b..3083c97e35 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -49,6 +49,18 @@ namespace MWClass ///< Return name of inventory icon. virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu (default implementation: return a + /// null action). + + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const; + ///< \return Item health data available? (default implementation: false) + + virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; + ///< Return item max health or throw an exception, if class does not have item health + /// (default implementation: throw an exceoption) }; } diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp new file mode 100644 index 0000000000..f53ddc4305 --- /dev/null +++ b/apps/openmw/mwgui/repair.cpp @@ -0,0 +1,157 @@ +#include "repair.hpp" + +#include + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/class.hpp" + +#include "widgets.hpp" + +namespace MWGui +{ + +Repair::Repair(MWBase::WindowManager &parWindowManager) + : WindowBase("openmw_repair.layout", parWindowManager) +{ + getWidget(mRepairBox, "RepairBox"); + getWidget(mRepairView, "RepairView"); + getWidget(mToolBox, "ToolBox"); + getWidget(mToolIcon, "ToolIcon"); + getWidget(mUsesLabel, "UsesLabel"); + getWidget(mQualityLabel, "QualityLabel"); + getWidget(mCancelButton, "CancelButton"); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onCancel); +} + +void Repair::open() +{ + center(); +} + +void Repair::startRepairItem(const MWWorld::Ptr &item) +{ + mRepair.setTool(item); + + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(item).getInventoryIcon(item); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + mToolIcon->setImageTexture (path); + mToolIcon->setUserString("ToolTipType", "ItemPtr"); + mToolIcon->setUserData(item); + + updateRepairView(); +} + +void Repair::updateRepairView() +{ + MWWorld::LiveCellRef *ref = + mRepair.getTool().get(); + + int uses = (mRepair.getTool().getCellRef().mCharge != -1) ? mRepair.getTool().getCellRef().mCharge : ref->mBase->mData.mUses; + + float quality = ref->mBase->mData.mQuality; + + std::stringstream qualityStr; + qualityStr << std::setprecision(3) << quality; + + mUsesLabel->setCaptionWithReplacing("#{sUses} " + boost::lexical_cast(uses)); + mQualityLabel->setCaptionWithReplacing("#{sQuality} " + qualityStr.str()); + + bool toolBoxVisible = (mRepair.getTool().getRefData().getCount() != 0); + mToolBox->setVisible(toolBoxVisible); + + bool toolBoxWasVisible = (mRepairBox->getPosition().top != mToolBox->getPosition().top); + + if (toolBoxVisible && !toolBoxWasVisible) + { + // shrink + mRepairBox->setPosition(mRepairBox->getPosition() + MyGUI::IntPoint(0,mToolBox->getSize().height)); + mRepairBox->setSize(mRepairBox->getSize() - MyGUI::IntSize(0,mToolBox->getSize().height)); + } + else if (!toolBoxVisible && toolBoxWasVisible) + { + // expand + mRepairBox->setPosition(MyGUI::IntPoint (mRepairBox->getPosition().left, mToolBox->getPosition().top)); + mRepairBox->setSize(mRepairBox->getSize() + MyGUI::IntSize(0,mToolBox->getSize().height)); + } + + while (mRepairView->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mRepairView->getChildAt(0)); + + int currentY = 0; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor; + for (MWWorld::ContainerStoreIterator iter (store.begin(categories)); + iter!=store.end(); ++iter) + { + if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) + { + int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter); + int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; + if (maxDurability == durability) + continue; + + MyGUI::TextBox* text = mRepairView->createWidget ( + "SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default); + text->setCaption(MWWorld::Class::get(*iter).getName(*iter)); + text->setNeedMouseFocus(false); + currentY += 19; + + MyGUI::ImageBox* icon = mRepairView->createWidget ( + "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default); + std::string path = std::string("icons\\"); + path += MWWorld::Class::get(*iter).getInventoryIcon(*iter); + int pos = path.rfind("."); + path.erase(pos); + path.append(".dds"); + icon->setImageTexture (path); + icon->setUserString("ToolTipType", "ItemPtr"); + icon->setUserData(*iter); + icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem); + icon->eventMouseWheel += MyGUI::newDelegate(this, &Repair::onMouseWheel); + + Widgets::MWDynamicStatPtr chargeWidget = mRepairView->createWidget + ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default); + chargeWidget->setValue(durability, maxDurability); + chargeWidget->setNeedMouseFocus(false); + + currentY += 32 + 4; + } + } + mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY))); +} + +void Repair::onCancel(MyGUI::Widget *sender) +{ + mWindowManager.removeGuiMode(GM_Repair); +} + +void Repair::onRepairItem(MyGUI::Widget *sender) +{ + if (!mRepair.getTool().getRefData().getCount()) + return; + + mRepair.repair(*sender->getUserData()); + + updateRepairView(); +} + +void Repair::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (mRepairView->getViewOffset().top + _rel*0.3 > 0) + mRepairView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mRepairView->setViewOffset(MyGUI::IntPoint(0, mRepairView->getViewOffset().top + _rel*0.3)); +} + +} diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp new file mode 100644 index 0000000000..c14b1955bd --- /dev/null +++ b/apps/openmw/mwgui/repair.hpp @@ -0,0 +1,46 @@ +#ifndef OPENMW_MWGUI_REPAIR_H +#define OPENMW_MWGUI_REPAIR_H + +#include "window_base.hpp" + +#include "../mwworld/ptr.hpp" +#include "../mwmechanics/repair.hpp" + +namespace MWGui +{ + +class Repair : public WindowBase +{ +public: + Repair(MWBase::WindowManager &parWindowManager); + + virtual void open(); + + void startRepairItem (const MWWorld::Ptr& item); + +protected: + MyGUI::Widget* mRepairBox; + MyGUI::ScrollView* mRepairView; + + MyGUI::Widget* mToolBox; + + MyGUI::ImageBox* mToolIcon; + + MyGUI::TextBox* mUsesLabel; + MyGUI::TextBox* mQualityLabel; + + MyGUI::Button* mCancelButton; + + MWMechanics::Repair mRepair; + + void updateRepairView(); + + void onRepairItem (MyGUI::Widget* sender); + void onCancel (MyGUI::Widget* sender); + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + +}; + +} + +#endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 07ea726206..718bb7106e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -56,6 +56,7 @@ #include "cursor.hpp" #include "spellicons.hpp" #include "merchantrepair.hpp" +#include "repair.hpp" using namespace MWGui; @@ -92,6 +93,7 @@ WindowManager::WindowManager( , mEnchantingDialog(NULL) , mTrainingWindow(NULL) , mMerchantRepair(NULL) + , mRepair(NULL) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -183,6 +185,7 @@ WindowManager::WindowManager( mEnchantingDialog = new EnchantingDialog(*this); mTrainingWindow = new TrainingWindow(*this); mMerchantRepair = new MerchantRepair(*this); + mRepair = new Repair(*this); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -249,6 +252,7 @@ WindowManager::~WindowManager() delete mCountDialog; delete mQuickKeysMenu; delete mMerchantRepair; + delete mRepair; delete mCursor; cleanupGarbage(); @@ -308,6 +312,7 @@ void WindowManager::updateVisible() mEnchantingDialog->setVisible(false); mTrainingWindow->setVisible(false); mMerchantRepair->setVisible(false); + mRepair->setVisible(false); mHud->setVisible(mHudEnabled); @@ -436,6 +441,9 @@ void WindowManager::updateVisible() case GM_MerchantRepair: mMerchantRepair->setVisible(true); break; + case GM_Repair: + mRepair->setVisible(true); + break; case GM_InterMessageBox: break; case GM_Journal: @@ -1145,6 +1153,11 @@ void WindowManager::startRepair(MWWorld::Ptr actor) mMerchantRepair->startRepair(actor); } +void WindowManager::startRepairItem(MWWorld::Ptr item) +{ + mRepair->startRepairItem(item); +} + const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 2242a8467b..216ab9a6f8 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -75,6 +75,7 @@ namespace MWGui class Cursor; class SpellIcons; class MerchantRepair; + class Repair; class WindowManager : public MWBase::WindowManager { @@ -231,6 +232,7 @@ namespace MWGui virtual void startEnchanting(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor); virtual void startRepair(MWWorld::Ptr actor); + virtual void startRepairItem(MWWorld::Ptr item); virtual void changePointer (const std::string& name); @@ -269,6 +271,7 @@ namespace MWGui EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; MerchantRepair* mMerchantRepair; + Repair* mRepair; Translation::Storage& mTranslationDataStorage; Cursor* mCursor; diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp new file mode 100644 index 0000000000..8ed4498859 --- /dev/null +++ b/apps/openmw/mwmechanics/repair.cpp @@ -0,0 +1,110 @@ +#include "repair.hpp" + +#include + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/class.hpp" + +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" + +namespace MWMechanics +{ + +void Repair::repair(const MWWorld::Ptr &itemToRepair) +{ + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::LiveCellRef *ref = + mTool.get(); + + // reduce number of uses left + int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses; + mTool.getCellRef().mCharge = uses-1; + + // unstack tool if required + if (mTool.getRefData().getCount() > 1 && uses == ref->mBase->mData.mUses) + { + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + MWWorld::ContainerStoreIterator it = store.add(mTool); + it->getRefData().setCount(mTool.getRefData().getCount()-1); + it->getCellRef().mCharge = -1; + + mTool.getRefData().setCount(1); + } + + MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); + MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player); + + float fatigueTerm = stats.getFatigueTerm(); + int pcStrength = stats.getAttribute(ESM::Attribute::Strength).getModified(); + int pcLuck = stats.getAttribute(ESM::Attribute::Luck).getModified(); + int armorerSkill = npcStats.getSkill(ESM::Skill::Armorer).getModified(); + + float fRepairAmountMult = MWBase::Environment::get().getWorld()->getStore().get() + .find("fRepairAmountMult")->getFloat(); + + float toolQuality = ref->mBase->mData.mQuality; + + float x = (0.1 * pcStrength + 0.1 * pcLuck + armorerSkill) * fatigueTerm; + + int roll = static_cast (std::rand()) / RAND_MAX * 100; + if (roll <= x) + { + int y = fRepairAmountMult * toolQuality * roll; + y = std::max(1, y); + + // repair by 'y' points + itemToRepair.getCellRef().mCharge += y; + itemToRepair.getCellRef().mCharge = std::min(itemToRepair.getCellRef().mCharge, + MWWorld::Class::get(itemToRepair).getItemMaxHealth(itemToRepair)); + + // set the OnPCRepair variable on the item's script + std::string script = MWWorld::Class::get(itemToRepair).getScript(itemToRepair); + if(script != "") + itemToRepair.getRefData().getLocals().setVarByInt(script, "onpcrepair", 1); + + // increase skill + MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Armorer, 0); + + MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); + MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairSuccess}"); + } + else + { + MWBase::Environment::get().getSoundManager()->playSound("Repair Fail",1,1); + MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairFailed}"); + } + + // tool used up? + if (mTool.getCellRef().mCharge == 0) + { + mTool.getRefData().setCount(0); + + std::string message = MWBase::Environment::get().getWorld()->getStore().get() + .find("sNotifyMessage51")->getString(); + + MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % MWWorld::Class::get(mTool).getName(mTool)).str()); + + // try to find a new tool of the same ID + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + for (MWWorld::ContainerStoreIterator iter (store.begin()); + iter!=store.end(); ++iter) + { + if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, mTool.getCellRef().mRefID)) + { + mTool = *iter; + break; + } + } + } +} + +} diff --git a/apps/openmw/mwmechanics/repair.hpp b/apps/openmw/mwmechanics/repair.hpp new file mode 100644 index 0000000000..6f9a866af1 --- /dev/null +++ b/apps/openmw/mwmechanics/repair.hpp @@ -0,0 +1,23 @@ +#ifndef OPENMW_MWMECHANICS_REPAIR_H +#define OPENMW_MWMECHANICS_REPAIR_H + +#include "../mwworld/ptr.hpp" + +namespace MWMechanics +{ + + class Repair + { + public: + void setTool (const MWWorld::Ptr& tool) { mTool = tool; } + MWWorld::Ptr getTool() { return mTool; } + + void repair (const MWWorld::Ptr& itemToRepair); + + private: + MWWorld::Ptr mTool; + }; + +} + +#endif diff --git a/apps/openmw/mwworld/actionrepair.cpp b/apps/openmw/mwworld/actionrepair.cpp new file mode 100644 index 0000000000..bd56421165 --- /dev/null +++ b/apps/openmw/mwworld/actionrepair.cpp @@ -0,0 +1,18 @@ +#include "actionrepair.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" + +namespace MWWorld +{ + ActionRepair::ActionRepair(const Ptr &item) + : Action(false, item) + { + } + + void ActionRepair::executeImp (const Ptr& actor) + { + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair); + MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget()); + } +} diff --git a/apps/openmw/mwworld/actionrepair.hpp b/apps/openmw/mwworld/actionrepair.hpp new file mode 100644 index 0000000000..1d3ef2bc11 --- /dev/null +++ b/apps/openmw/mwworld/actionrepair.hpp @@ -0,0 +1,17 @@ +#ifndef GAME_MWWORLD_ACTIONREPAIR_H +#define GAME_MWWORLD_ACTIONREPAIR_H + +#include "action.hpp" + +namespace MWWorld +{ + class ActionRepair : public Action + { + virtual void executeImp (const Ptr& actor); + + public: + ActionRepair(const MWWorld::Ptr& item); + }; +} + +#endif diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 223514e086..ac27beb44a 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -38,12 +38,6 @@ namespace return sum; } - - bool compare_string_ci(std::string str1, std::string str2) - { - Misc::StringUtils::toLower(str1); - return str1 == str2; - } } MWWorld::ContainerStore::ContainerStore() : mStateId (0), mCachedWeight (0), mWeightUpToDate (false) {} @@ -68,7 +62,11 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier) && ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner && ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul - && ptr1.mCellRef->mCharge == -1) // item that is already partly used up never stacks + // item that is already partly used up never stacks + && (!MWWorld::Class::get(ptr1).hasItemHealth(ptr1) || ptr1.mCellRef->mCharge == -1 + || MWWorld::Class::get(ptr1).getItemMaxHealth(ptr1) == ptr1.mCellRef->mCharge) + && (!MWWorld::Class::get(ptr2).hasItemHealth(ptr2) || ptr2.mCellRef->mCharge == -1 + || MWWorld::Class::get(ptr2).getItemMaxHealth(ptr2) == ptr2.mCellRef->mCharge)) return true; return false; @@ -118,11 +116,11 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr) MWWorld::LiveCellRef *gold = ptr.get(); - if (compare_string_ci(gold->mRef.mRefID, "gold_001") - || compare_string_ci(gold->mRef.mRefID, "gold_005") - || compare_string_ci(gold->mRef.mRefID, "gold_010") - || compare_string_ci(gold->mRef.mRefID, "gold_025") - || compare_string_ci(gold->mRef.mRefID, "gold_100")) + if (Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_001") + || Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_005") + || Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_010") + || Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_025") + || Misc::StringUtils::ciEqual(gold->mRef.mRefID, "gold_100")) { MWWorld::ManualRef ref(esmStore, "Gold_001"); @@ -130,7 +128,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr) ref.getPtr().getRefData().setCount(count); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (compare_string_ci((*iter).get()->mRef.mRefID, "gold_001")) + if (Misc::StringUtils::ciEqual((*iter).get()->mRef.mRefID, "gold_001")) { (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); flagAsModified(); diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 4adebf1dfd..7da28f0bfa 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -79,6 +79,7 @@ set(MYGUI_FILES openmw_travel_window.layout openmw_persuasion_dialog.layout openmw_merchantrepair.layout + openmw_repair.layout smallbars.png DejaVuLGCSansMono.ttf markers.png diff --git a/files/mygui/openmw_repair.layout b/files/mygui/openmw_repair.layout new file mode 100644 index 0000000000..2881a5853a --- /dev/null +++ b/files/mygui/openmw_repair.layout @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 13b22ff93d..71e86091c8 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -154,8 +154,8 @@ - - + + From 92f00989110bf3371f9be5ffe6b79f8903858c02 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 23 Mar 2013 13:13:34 +0100 Subject: [PATCH 25/47] added new constructors for EnumDelegateFactory --- apps/opencs/view/world/enumdelegate.cpp | 11 +++++++++++ apps/opencs/view/world/enumdelegate.hpp | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 7a8b45373d..0dd0a1d594 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -1,6 +1,7 @@ #include "enumdelegate.hpp" +#include #include #include @@ -89,6 +90,16 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte } +CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} + +CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names) +{ + assert (names); + + for (int i=0; names[i]; ++i) + add (i, names[i]); +} + CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack, QObject *parent) const { diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index f11252371e..752ed5be72 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -45,6 +45,11 @@ namespace CSVWorld public: + EnumDelegateFactory(); + + EnumDelegateFactory (const char **names); + ///< \param names Array of char pointer with a 0-pointer as end mark + virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. From 0ce962e815bb0f08e2ddfbf576efa216da2b1aa7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 23 Mar 2013 13:13:53 +0100 Subject: [PATCH 26/47] added specialisation column to skill table --- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/view/doc/viewmanager.cpp | 8 ++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index c44abda2b2..a098fcb7e5 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -31,7 +31,8 @@ namespace CSMWorld Display_Float, Display_Var, Display_GmstVarType, - Display_GlobalVarType + Display_GlobalVarType, + Display_Specialisation }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index a84c9ddf64..43aad889d9 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -202,6 +202,31 @@ namespace CSMWorld return true; } }; + + template + struct SpecialisationColumn : public Column + { + SpecialisationColumn() : Column ("Specialisation", ColumnBase::Display_Specialisation) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mSpecialization; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mSpecialization = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 51ea3e71be..de85beed45 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -38,6 +38,7 @@ CSMWorld::Data::Data() mSkills.addColumn (new StringIdColumn); mSkills.addColumn (new RecordStateColumn); + mSkills.addColumn (new SpecialisationColumn); mSkills.addColumn (new DescriptionColumn); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 33300f67a7..f59be3d997 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -38,6 +38,11 @@ void CSVDoc::ViewManager::updateIndices() CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false) { + static const char *sSpecialisations[] = + { + "Combat", "Magic", "Stealth", 0 + }; + mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, @@ -45,6 +50,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); + + mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation, + new CSVWorld::EnumDelegateFactory (sSpecialisations)); } CSVDoc::ViewManager::~ViewManager() From 962b5041296cdf3a0422b9f0c0f29e49a5f2bd5f Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 23 Mar 2013 16:20:10 +0100 Subject: [PATCH 27/47] add dpkg information for mwiniimporter, this blocked debian/ubuntu buildd from building --- apps/mwiniimporter/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt index deab88ce28..702f665138 100644 --- a/apps/mwiniimporter/CMakeLists.txt +++ b/apps/mwiniimporter/CMakeLists.txt @@ -22,3 +22,8 @@ if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(mwiniimport gcov) endif() + +if(DPKG_PROGRAM) + INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport) +endif() + From 4208d52b1ac67ae40f43d190c8a7aadeff3c3f06 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 24 Mar 2013 14:51:48 +0100 Subject: [PATCH 28/47] added use value columns to skills --- apps/opencs/model/world/columns.hpp | 32 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 3 ++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 43aad889d9..1836dbe7f4 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WOLRD_COLUMNS_H #define CSM_WOLRD_COLUMNS_H +#include + #include "columnbase.hpp" namespace CSMWorld @@ -227,6 +229,36 @@ namespace CSMWorld return true; } }; + + template + struct UseValueColumn : public Column + { + int mIndex; + + UseValueColumn (int index) + : Column ("Use value #" + boost::lexical_cast (index), + ColumnBase::Display_Float), mIndex (index) + {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mUseValue[mIndex]; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mUseValue[mIndex] = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index de85beed45..1b65fecc03 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -39,7 +39,8 @@ CSMWorld::Data::Data() mSkills.addColumn (new StringIdColumn); mSkills.addColumn (new RecordStateColumn); mSkills.addColumn (new SpecialisationColumn); - + for (int i=0; i<4; ++i) + mSkills.addColumn (new UseValueColumn (i)); mSkills.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); From 114f99ddbf0b0e6fb99c116e0622ab9da7dbd47d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 24 Mar 2013 15:10:03 +0100 Subject: [PATCH 29/47] add skill records when creating a new base file --- apps/opencs/model/doc/document.cpp | 10 ++++++++++ apps/opencs/model/world/data.cpp | 10 ++++++++++ apps/opencs/model/world/data.hpp | 4 ++++ components/esm/loadskil.cpp | 32 ++++++++++++++++++------------ components/esm/loadskil.hpp | 2 ++ 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 47cf1f6642..deafe8eb84 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -198,6 +198,16 @@ void CSMDoc::Document::createBase() } /// \todo add GMSTs + + for (int i=0; i<27; ++i) + { + ESM::Skill record; + record.mIndex = i; + record.mId = ESM::Skill::getIndexToId (record.mIndex); + record.blank(); + + getData().getSkills().add (record); + } } CSMDoc::Document::Document (const std::vector& files, bool new_) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 1b65fecc03..bc78cb46be 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -74,6 +74,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getGmsts() return mGmsts; } +const CSMWorld::IdCollection& CSMWorld::Data::getSkills() const +{ + return mSkills; +} + +CSMWorld::IdCollection& CSMWorld::Data::getSkills() +{ + return mSkills; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index dc9aee0618..ac953dbece 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -46,6 +46,10 @@ namespace CSMWorld IdCollection& getGmsts(); + const IdCollection& getSkills() const; + + IdCollection& getSkills(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index ac9fc27897..b9d588eef4 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -103,19 +103,7 @@ void Skill::load(ESMReader &esm) // create an ID from the index and the name (only used in the editor and likely to change in the // future) - std::ostringstream stream; - - stream << "#"; - - if (mIndex<10) - stream << "0"; - - stream << mIndex; - - if (mIndex>=0 && mIndex=0 && index Date: Sun, 24 Mar 2013 15:50:29 +0100 Subject: [PATCH 30/47] added attribute column to skills --- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/columns.hpp | 26 ++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/view/doc/viewmanager.cpp | 9 +++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index a098fcb7e5..b5863f8e4e 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -32,7 +32,8 @@ namespace CSMWorld Display_Var, Display_GmstVarType, Display_GlobalVarType, - Display_Specialisation + Display_Specialisation, + Display_Attribute }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 1836dbe7f4..7764f58709 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -259,6 +259,32 @@ namespace CSMWorld return true; } }; + + template + struct AttributeColumn : public Column + { + AttributeColumn() : Column ("Attribute", ColumnBase::Display_Attribute) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mAttribute; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mAttribute = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index bc78cb46be..4b10a66836 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -38,6 +38,7 @@ CSMWorld::Data::Data() mSkills.addColumn (new StringIdColumn); mSkills.addColumn (new RecordStateColumn); + mSkills.addColumn (new AttributeColumn); mSkills.addColumn (new SpecialisationColumn); for (int i=0; i<4; ++i) mSkills.addColumn (new UseValueColumn (i)); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index f59be3d997..bc87728945 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -43,6 +43,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) "Combat", "Magic", "Stealth", 0 }; + static const char *sAttributes[] = + { + "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", + "Luck", 0 + }; + mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, @@ -53,6 +59,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation, new CSVWorld::EnumDelegateFactory (sSpecialisations)); + + mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute, + new CSVWorld::EnumDelegateFactory (sAttributes)); } CSVDoc::ViewManager::~ViewManager() From 7450554ef105bacd7e8ccc2e62d713b895b33a67 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 11:04:41 +0100 Subject: [PATCH 31/47] fixed a broken UniversalId constructor --- apps/opencs/model/world/universalid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 6fce376bea..57c276a6d3 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -45,7 +45,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string::size_type index = universalId.find (':'); - if (index==std::string::npos) + if (index!=std::string::npos) { std::string type = universalId.substr (0, index); From 739e7e7298e10c401ff18aba0637fb4879150164 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 11:06:40 +0100 Subject: [PATCH 32/47] improved record access from ID collection --- apps/opencs/model/world/idcollection.hpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 9b69dfb889..3bf53349e6 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -74,6 +74,8 @@ namespace CSMWorld virtual const RecordBase& getRecord (const std::string& id) const = 0; + virtual const RecordBase& getRecord (int index) const = 0; + virtual void load (ESM::ESMReader& reader, bool base) = 0; }; @@ -139,7 +141,9 @@ namespace CSMWorld /// /// \attention Throw san exception, if the type of \a record does not match. - virtual const RecordBase& getRecord (const std::string& id) const; + virtual const Record& getRecord (const std::string& id) const; + + virtual const Record& getRecord (int index) const; virtual void load (ESM::ESMReader& reader, bool base); @@ -373,11 +377,18 @@ namespace CSMWorld } template - const RecordBase& IdCollection::getRecord (const std::string& id) const + const Record& IdCollection::getRecord (const std::string& id) const { int index = getIndex (id); return mRecords.at (index); } + + template + const Record& IdCollection::getRecord (int index) const + { + return mRecords.at (index); + } + } #endif From dc67ddf39b43c41e3109b71a03122906214d1d68 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 11:07:04 +0100 Subject: [PATCH 33/47] added verifier stage for skill records --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/skillcheck.cpp | 37 ++++++++++++++++++++++++++ apps/opencs/model/tools/skillcheck.hpp | 29 ++++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 3 +++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/skillcheck.cpp create mode 100644 apps/opencs/model/tools/skillcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 488e3c65f5..a305d90d93 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,7 +35,7 @@ opencs_units (model/tools ) opencs_units_noqt (model/tools - stage verifier mandatoryid + stage verifier mandatoryid skillcheck ) diff --git a/apps/opencs/model/tools/skillcheck.cpp b/apps/opencs/model/tools/skillcheck.cpp new file mode 100644 index 0000000000..897aeab473 --- /dev/null +++ b/apps/opencs/model/tools/skillcheck.cpp @@ -0,0 +1,37 @@ + +#include "skillcheck.hpp" + +#include + +#include + +#include "../world/universalid.hpp" + +CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection& skills) +: mSkills (skills) +{} + +int CSMTools::SkillCheckStage::setup() +{ + return mSkills.getSize(); +} + +void CSMTools::SkillCheckStage::perform (int stage, std::vector& messages) +{ + const ESM::Skill& skill = mSkills.getRecord (stage).get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId); + + for (int i=0; i<4; ++i) + if (skill.mData.mUseValue[i]<0) + { + std::ostringstream stream; + + stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative"; + + messages.push_back (stream.str()); + } + + if (skill.mDescription.empty()) + messages.push_back (id.toString() + "|" + skill.mId + " has an empty description"); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/skillcheck.hpp b/apps/opencs/model/tools/skillcheck.hpp new file mode 100644 index 0000000000..30a3f01cad --- /dev/null +++ b/apps/opencs/model/tools/skillcheck.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_TOOLS_SKILLCHECK_H +#define CSM_TOOLS_SKILLCHECK_H + +#include + +#include "../world/idcollection.hpp" + +#include "stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that skill records are internally consistent + class SkillCheckStage : public Stage + { + const CSMWorld::IdCollection& mSkills; + + public: + + SkillCheckStage (const CSMWorld::IdCollection& skills); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8dd1c0fe6f..33cc3cc61b 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -12,6 +12,7 @@ #include "reportmodel.hpp" #include "mandatoryid.hpp" +#include "skillcheck.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) { @@ -51,6 +52,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); + + mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); } return mVerifier; From 6c76e97bbc65e8ae101dc6fe7bf427e30a5974fe Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 11:53:02 +0100 Subject: [PATCH 34/47] fixed day count in rest dialogue --- apps/openmw/mwgui/waitdialog.cpp | 20 ++++++++++---------- apps/openmw/mwworld/globals.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 6e914a669b..df8a52456c 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -132,7 +132,7 @@ namespace MWGui case 11: month = "#{sMonthEveningstar}"; break; - default: + default: break; } int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour (); @@ -142,7 +142,7 @@ namespace MWGui std::string dateTimeText = boost::lexical_cast(MWBase::Environment::get().getWorld ()->getDay ()) + " " - + month + " (#{sDay} " + boost::lexical_cast(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay ()+1) + + month + " (#{sDay} " + boost::lexical_cast(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay()) + ") " + boost::lexical_cast(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}"); mDateTimeText->setCaptionWithReplacing (dateTimeText); @@ -156,13 +156,13 @@ namespace MWGui MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats stats = MWWorld::Class::get(player).getCreatureStats(player); const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - + float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1; - + bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0); float fRestMagicMult = store.get().find("fRestMagicMult")->getFloat(); float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified(); - + // this massive duplication is why it has to be put into helper functions instead float fFatigueReturnBase = store.get().find("fFatigueReturnBase")->getFloat(); float fFatigueReturnMult = store.get().find("fFatigueReturnMult")->getFloat(); @@ -174,7 +174,7 @@ namespace MWGui normalizedEncumbrance = 1; float hourlyFatigueDelta = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); hourlyFatigueDelta *= 3600 * fEndFatigueMult * stats.getAttribute(ESM::Attribute::Endurance).getModified(); - + float healthHours = hourlyHealthDelta >= 0.0 ? (stats.getHealth().getBase() - stats.getHealth().getCurrent()) / hourlyHealthDelta : 1.0f; @@ -185,9 +185,9 @@ namespace MWGui float fatigueHours = hourlyFatigueDelta >= 0.0 ? (stats.getFatigue().getBase() - stats.getFatigue().getCurrent()) / hourlyFatigueDelta : 1.0f; - + int autoHours = int(std::ceil( std::max(std::max(healthHours, magickaHours), std::max(fatigueHours, 1.0f)) )); // this should use a variadic max if possible - + startWaiting(autoHours); } @@ -201,11 +201,11 @@ namespace MWGui MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2); setVisible(false); mProgressBar.setVisible (true); - + mWaiting = true; mCurHour = 0; mHours = hoursToWait; - + mRemainingTime = 0.05; mProgressBar.setProgress (0, mHours); } diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 9e57910ee0..72bebc0498 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -79,7 +79,7 @@ namespace MWWorld { // vanilla Morrowind does not define dayspassed. Data value; - value.mLong = 0; + value.mLong = 1; // but the addons start counting at 1 :( mVariables.insert (std::make_pair ("dayspassed", std::make_pair ('l', value))); } From f39f6946389525699faefdb8e5aedba30040bee5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 11:59:25 +0100 Subject: [PATCH 35/47] various global variable fixes in editor --- apps/opencs/model/doc/document.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index deafe8eb84..d1462d6a3f 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -150,6 +150,10 @@ void CSMDoc::Document::addOptionalGlobals() ESM::Global global; global.mId = sGlobals[i]; global.mValue.setType (ESM::VT_Long); + + if (i==0) + global.mValue.setInteger (1); // dayspassed starts counting at 1 + addOptionalGlobal (global); } } @@ -189,9 +193,9 @@ void CSMDoc::Document::createBase() record.mId = sGlobals[i]; - record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int); + record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Long); - if (i==0) + if (i==0 || i==1) record.mValue.setInteger (1); getData().getGlobals().add (record); From f2969e7143d9f050bc2745c54de3a65850db5189 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 12:56:52 +0100 Subject: [PATCH 36/47] fixed access to records flagged as deleted --- apps/opencs/model/world/record.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index e442d0a391..c8f728e7d1 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -62,7 +62,7 @@ namespace CSMWorld if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); - return mState==State_BaseOnly ? mBase : mModified; + return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified; } template From 4be0c6b70867f3514c088c522f687d45da855dd6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 25 Mar 2013 17:32:01 +0100 Subject: [PATCH 37/47] Fix topics not being selectable for creatures --- apps/openmw/mwgui/dialogue.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 9a7e51874f..d045725fb1 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -230,14 +230,14 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id) { if (!mEnabled) return; - int separatorPos = mTopicsList->getItemCount(); + int separatorPos = 0; for (unsigned int i=0; igetItemCount(); ++i) { if (mTopicsList->getItemNameAt(i) == "") separatorPos = i; } - if (id > separatorPos) + if (id >= separatorPos) MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic)); else { From 6a2b87e14a5ed565caf4f7e208c9c398d8a6611a Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 25 Mar 2013 17:37:59 +0100 Subject: [PATCH 38/47] Fix dialogue response coloring for creatures --- apps/openmw/mwgui/dialogue.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index d045725fb1..bfbd60b07d 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -389,10 +389,17 @@ std::string DialogueWindow::parseText(const std::string& text) std::vector topics; + bool hasSeparator = false; + for (unsigned int i=0; igetItemCount(); ++i) + { + if (mTopicsList->getItemNameAt(i) == "") + hasSeparator = true; + } + for(unsigned int i = 0;igetItemCount();i++) { std::string keyWord = mTopicsList->getItemNameAt(i); - if (separatorReached) + if (separatorReached || !hasSeparator) topics.push_back(keyWord); else if (keyWord == "") separatorReached = true; From 6f1575d42a046bff854f0a79cb834e6aaf38f4fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Mar 2013 17:27:43 +0100 Subject: [PATCH 39/47] CELL record corrections --- apps/esmtool/esmtool.cpp | 5 ++++- apps/openmw/mwclass/misc.cpp | 13 +++++++++---- apps/openmw/mwworld/containerstore.cpp | 3 ++- apps/openmw/mwworld/manualref.hpp | 5 +++-- components/esm/loadcell.cpp | 24 ++++++++++++++++-------- components/esm/loadcell.hpp | 12 +++++++++--- 6 files changed, 43 insertions(+), 19 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 521383f3ff..d682cf88b9 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -227,7 +227,10 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) std::cout << " Refnum: " << ref.mRefnum << std::endl; std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " Owner: '" << ref.mOwner << "'\n"; - std::cout << " Uses/health: " << ref.mCharge << " NAM9: " << ref.mNam9 << std::endl; + std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n"; + std::cout << " Uses/health: '" << ref.mCharge << "'\n"; + std::cout << " Gold value: '" << ref.mGoldValue << "'\n"; + std::cout << " Blocked: '" << static_cast(ref.mReferenceBlocked) << "'" << std::endl; } } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 07e41bcfa6..31ae1cfb05 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -89,7 +89,9 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mData.mValue; + int value = (ptr.getCellRef().mGoldValue == 1) ? ref->mBase->mData.mValue : ptr.getCellRef().mGoldValue; + + return value; } void Miscellaneous::registerSelf() @@ -151,8 +153,10 @@ namespace MWClass int count = ptr.getRefData().getCount(); bool isGold = (ref->mBase->mName == store.get().find("sGold")->getString()); - if (isGold && count == 1) - count = ref->mBase->mData.mValue; + if (isGold && ptr.getCellRef().mGoldValue != 1) + count = ptr.getCellRef().mGoldValue; + else if (isGold) + count *= ref->mBase->mData.mValue; std::string countString; if (!isGold) @@ -214,7 +218,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = newRef.getPtr().get(); newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell); - newPtr.getRefData ().setCount(goldAmount); + newPtr.getRefData ().setCount(1); + newPtr.getCellRef().mGoldValue = goldAmount; } else { MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index ac27beb44a..e5b68841b8 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -124,7 +124,8 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr) { MWWorld::ManualRef ref(esmStore, "Gold_001"); - int count = (ptr.getRefData().getCount() == 1) ? gold->mBase->mData.mValue : ptr.getRefData().getCount(); + int count = MWWorld::Class::get(ptr).getValue(ptr) * ptr.getRefData().getCount(); + ref.getPtr().getRefData().setCount(count); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 58395d8798..6616165fae 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -69,10 +69,11 @@ namespace MWWorld cellRef.mScale = 1; cellRef.mFactIndex = 0; cellRef.mCharge = -1; - cellRef.mNam9 = 0; + cellRef.mGoldValue = 1; + cellRef.mEnchantmentCharge = -1; cellRef.mTeleport = false; cellRef.mLockLevel = 0; - cellRef.mUnam = 0; + cellRef.mReferenceBlocked = 0; } const Ptr& getPtr() const diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 0731a8ff80..5cbf1de2b7 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -43,11 +43,14 @@ void CellRef::save(ESMWriter &esm) esm.writeHNT("INDX", mFactIndex); } + if (mEnchantmentCharge != -1) + esm.writeHNT("XCHG", mEnchantmentCharge); + if (mCharge != -1) esm.writeHNT("INTV", mCharge); - if (mNam9 != 0) { - esm.writeHNT("NAM9", mNam9); + if (mGoldValue != 1) { + esm.writeHNT("NAM9", mGoldValue); } if (mTeleport) @@ -62,8 +65,8 @@ void CellRef::save(ESMWriter &esm) esm.writeHNOCString("KNAM", mKey); esm.writeHNOCString("TNAM", mTrap); - if (mUnam != -1) { - esm.writeHNT("UNAM", mUnam); + if (mReferenceBlocked != -1) { + esm.writeHNT("UNAM", mReferenceBlocked); } if (mFltv != 0) { esm.writeHNT("FLTV", mFltv); @@ -281,10 +284,15 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) ref.mFactIndex = -2; esm.getHNOT(ref.mFactIndex, "INDX"); - ref.mNam9 = 0; + ref.mGoldValue = 1; ref.mCharge = -1; + ref.mEnchantmentCharge = -1; + + esm.getHNOT(ref.mEnchantmentCharge, "XCHG"); + esm.getHNOT(ref.mCharge, "INTV"); - esm.getHNOT(ref.mNam9, "NAM9"); + + esm.getHNOT(ref.mGoldValue, "NAM9"); // Present for doors that teleport you to another cell. if (esm.isNextSub("DODT")) @@ -302,9 +310,9 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) ref.mKey = esm.getHNOString("KNAM"); ref.mTrap = esm.getHNOString("TNAM"); - ref.mUnam = -1; + ref.mReferenceBlocked = -1; ref.mFltv = 0; - esm.getHNOT(ref.mUnam, "UNAM"); + esm.getHNOT(ref.mReferenceBlocked, "UNAM"); esm.getHNOT(ref.mFltv, "FLTV"); esm.getHNOT(ref.mPos, "DATA", 24); diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 97aa86ba0f..afc953f54c 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -56,7 +56,11 @@ public: // For tools (lockpicks, probes, repair hammer) it is the remaining uses. int mCharge; - int mNam9; + // Remaining enchantment charge + float mEnchantmentCharge; + + // This is 5 for Gold_005 references, 100 for Gold_100 and so on. + int mGoldValue; // For doors - true if this door teleports to somewhere else, false // if it should open through animation. @@ -72,8 +76,10 @@ public: int mLockLevel; std::string mKey, mTrap; // Key and trap ID names, if any - // No idea - occurs ONCE in Morrowind.esm, for an activator - signed char mUnam; + // This corresponds to the "Reference Blocked" checkbox in the construction set, + // which prevents editing that reference. + // -1 is not blocked, otherwise it is blocked. + signed char mReferenceBlocked; // Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn. int mDeleted; From 406488d086f78006256b00416f829fefd5b9b170 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Mar 2013 17:39:49 +0100 Subject: [PATCH 40/47] Soulgem value should be multiplied by the trapped soul --- apps/openmw/mwclass/misc.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 31ae1cfb05..b971fa6f34 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -91,6 +91,12 @@ namespace MWClass int value = (ptr.getCellRef().mGoldValue == 1) ? ref->mBase->mData.mValue : ptr.getCellRef().mGoldValue; + if (ptr.getCellRef().mSoul != "") + { + const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get().find(ref->mRef.mSoul); + value *= creature->mData.mSoul; + } + return value; } @@ -178,7 +184,7 @@ namespace MWClass if (!isGold) { text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); + text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); } if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { From 564256c4e13f9ea2348de901fc73e0f0fe1d2eae Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Mar 2013 18:04:15 +0100 Subject: [PATCH 41/47] Fix the spell icon panel being visible when it shouldn't. --- apps/openmw/mwgui/spellicons.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 16e02ebba1..206db51ed0 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -139,12 +139,13 @@ namespace MWGui } } - parent->setVisible(effects.size() != 0); - int w=2; + if (adjustSize) { int s = effects.size() * 16+4; + if (!effects.size()) + s = 0; int diff = parent->getWidth() - s; parent->setSize(s, parent->getHeight()); parent->setPosition(parent->getLeft()+diff, parent->getTop()); From 6643fe789cb3a909af82f245b8b743c4853bf11d Mon Sep 17 00:00:00 2001 From: Glorf Date: Thu, 28 Mar 2013 17:41:00 +0100 Subject: [PATCH 42/47] Enchanting system --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 39 +++-- apps/openmw/mwclass/armor.cpp | 15 ++ apps/openmw/mwclass/armor.hpp | 2 + apps/openmw/mwclass/book.cpp | 24 ++++ apps/openmw/mwclass/book.hpp | 4 + apps/openmw/mwclass/clothing.cpp | 15 ++ apps/openmw/mwclass/clothing.hpp | 2 + apps/openmw/mwclass/weapon.cpp | 15 ++ apps/openmw/mwclass/weapon.hpp | 2 + apps/openmw/mwgui/enchantingdialog.cpp | 104 ++++++++++++-- apps/openmw/mwgui/enchantingdialog.hpp | 13 +- apps/openmw/mwgui/spellcreationdialog.cpp | 10 +- apps/openmw/mwgui/spellcreationdialog.hpp | 5 +- apps/openmw/mwmechanics/enchanting.cpp | 164 ++++++++++++++++++++++ apps/openmw/mwmechanics/enchanting.hpp | 41 ++++++ apps/openmw/mwworld/class.cpp | 5 + apps/openmw/mwworld/class.hpp | 2 + apps/openmw/mwworld/worldimp.cpp | 25 ++++ apps/openmw/mwworld/worldimp.hpp | 29 +++- 20 files changed, 482 insertions(+), 36 deletions(-) create mode 100644 apps/openmw/mwmechanics/enchanting.cpp create mode 100644 apps/openmw/mwmechanics/enchanting.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0edc18afba..7b79a8fdf5 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -64,7 +64,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow - aiescort aiactivate + aiescort aiactivate enchanting ) add_openmw_dir (mwbase diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 642291eefb..041e2cc1c1 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -243,27 +243,44 @@ namespace MWBase ///< Toggle a render mode. ///< \return Resulting mode - virtual const ESM::Potion *createRecord (const ESM::Potion& record) - = 0; - ///< Create a new recrod (of type potion) in the ESM store. + virtual const ESM::Potion *createRecord (const ESM::Potion& record) = 0; + ///< Create a new record (of type potion) in the ESM store. /// \return pointer to created record - virtual const ESM::Spell *createRecord (const ESM::Spell& record) - = 0; - ///< Create a new recrod (of type spell) in the ESM store. + virtual const ESM::Spell *createRecord (const ESM::Spell& record) = 0; + ///< Create a new record (of type spell) in the ESM store. /// \return pointer to created record - virtual const ESM::Class *createRecord (const ESM::Class& record) - = 0; - ///< Create a new recrod (of type class) in the ESM store. + virtual const ESM::Class *createRecord (const ESM::Class& record) = 0; + ///< Create a new record (of type class) in the ESM store. /// \return pointer to created record virtual const ESM::Cell *createRecord (const ESM::Cell& record) = 0; - ///< Create a new recrod (of type cell) in the ESM store. + ///< Create a new record (of type cell) in the ESM store. /// \return pointer to created record virtual const ESM::NPC *createRecord(const ESM::NPC &record) = 0; - ///< Create a new recrod (of type npc) in the ESM store. + ///< Create a new record (of type npc) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Armor *createRecord (const ESM::Armor& record) = 0; + ///< Create a new record (of type armor) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Weapon *createRecord (const ESM::Weapon& record) = 0; + ///< Create a new record (of type weapon) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Clothing *createRecord (const ESM::Clothing& record) = 0; + ///< Create a new record (of type clothing) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Enchantment *createRecord (const ESM::Enchantment& record) = 0; + ///< Create a new record (of type enchantment) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Book *createRecord (const ESM::Book& record) = 0; + ///< Create a new record (of type book) in the ESM store. /// \return pointer to created record virtual void update (float duration, bool paused) = 0; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 130c0515d0..02ed743dff 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -16,6 +16,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/manualref.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -273,6 +274,20 @@ namespace MWClass return ref->mBase->mEnchant; } + MWWorld::Ptr Armor::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + ESM::Armor oldItem = *store.get().find(ptr.getCellRef().mRefID); + ESM::Armor newItem = oldItem; + newItem.mId=""; + newItem.mName=newName; + newItem.mData.mEnchant=enchCharge; + newItem.mEnchant=enchId; + const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return ref.getPtr(); + } + boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index ff45411ed2..2c79321bb2 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -65,6 +65,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 4e29fa6845..9714bc06e7 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -11,6 +11,7 @@ #include "../mwworld/actionread.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/manualref.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -147,6 +148,21 @@ namespace MWClass return ref->mBase->mEnchant; } + MWWorld::Ptr Book::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + ESM::Book oldItem = *store.get().find(ptr.getCellRef().mRefID); + ESM::Book newItem = oldItem; + newItem.mId=""; + newItem.mName=newName; + newItem.mData.mIsScroll = 1; + newItem.mData.mEnchant=enchCharge; + newItem.mEnchant=enchId; + const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return ref.getPtr(); + } + boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const { return boost::shared_ptr(new MWWorld::ActionRead(ptr)); @@ -160,4 +176,12 @@ namespace MWClass return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell); } + + short Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mData.mEnchant; + } } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index acb1aac06e..950f2be413 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -51,10 +51,14 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu virtual std::string getModel(const MWWorld::Ptr &ptr) const; + + virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index f5f71a7767..813746fea2 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/manualref.hpp" #include "../mwgui/tooltips.hpp" @@ -221,6 +222,20 @@ namespace MWClass return ref->mBase->mEnchant; } + MWWorld::Ptr Clothing::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + ESM::Clothing oldItem = *store.get().find(ptr.getCellRef().mRefID); + ESM::Clothing newItem = oldItem; + newItem.mId=""; + newItem.mName=newName; + newItem.mData.mEnchant=enchCharge; + newItem.mEnchant=enchId; + const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return ref.getPtr(); + } + boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index f01c78afce..e705c113bf 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,6 +59,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 0f6e86811e..79ed66a501 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -14,6 +14,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/manualref.hpp" #include "../mwgui/tooltips.hpp" @@ -361,6 +362,20 @@ namespace MWClass return ref->mBase->mEnchant; } + MWWorld::Ptr Weapon::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + ESM::Weapon oldItem = *store.get().find(ptr.getCellRef().mRefID); + ESM::Weapon newItem = oldItem; + newItem.mId=""; + newItem.mName=newName; + newItem.mData.mEnchant=enchCharge; + newItem.mEnchant=enchId; + const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return ref.getPtr(); + } + boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const { boost::shared_ptr action(new MWWorld::ActionEquip(ptr)); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index bf34172516..24da3fe64a 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -65,6 +65,8 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 673739cbf3..5c31a32669 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -5,9 +5,11 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwworld/player.hpp" +#include "../mwworld/manualref.hpp" #include "itemselection.hpp" #include "container.hpp" +#include "inventorywindow.hpp" namespace MWGui { @@ -17,8 +19,9 @@ namespace MWGui : WindowBase("openmw_enchanting_dialog.layout", parWindowManager) , EffectEditorBase(parWindowManager) , mItemSelectionDialog(NULL) - , mCurrentEnchantmentPoints(0) + , mEnchanting(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { + getWidget(mName, "NameEdit"); getWidget(mCancelButton, "CancelButton"); getWidget(mAvailableEffectsList, "AvailableEffects"); getWidget(mUsedEffectsView, "UsedEffects"); @@ -36,6 +39,8 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onCancelButtonClicked); mItemBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectItem); mSoulBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectSoul); + mBuyButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onBuyButtonClicked); + mTypeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onTypeButtonClicked); } EnchantingDialog::~EnchantingDialog() @@ -52,9 +57,32 @@ namespace MWGui void EnchantingDialog::updateLabels() { - mEnchantmentPoints->setCaption(boost::lexical_cast(mCurrentEnchantmentPoints) - + " / " + (mItem.isEmpty() ? "0" : boost::lexical_cast( - MWWorld::Class::get(mItem).getEnchantmentPoints(mItem)))); + mEnchantmentPoints->setCaption(boost::lexical_cast(mEnchanting.getEnchantCost()) + + " / " + boost::lexical_cast(mEnchanting.getMaxEnchantValue())); + + mCharge->setCaption(boost::lexical_cast(mEnchanting.getGemCharge())); + + mCastCost->setCaption(boost::lexical_cast(mEnchanting.getEnchantCost())); + + switch(mEnchanting.getEnchantType()) + { + case 0: + mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastOnce","Cast Once")); + mAddEffectDialog.constantEffect=false; + break; + case 1: + mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenStrikes", "When Strikes")); + mAddEffectDialog.constantEffect=false; + break; + case 2: + mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastWhenUsed", "When Used")); + mAddEffectDialog.constantEffect=false; + break; + case 3: + mTypeButton->setCaption(mWindowManager.getGameSettingString("sItemCastConstant", "Cast Constant")); + mAddEffectDialog.constantEffect=true; + break; + } } void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) @@ -105,7 +133,8 @@ namespace MWGui image->setUserData(item); image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem); - mItem = item; + mEnchanting.setOldItem(item); + mEnchanting.nextEnchantType(); updateLabels(); } @@ -113,7 +142,7 @@ namespace MWGui { while (mItemBox->getChildCount ()) MyGUI::Gui::getInstance ().destroyWidget (mItemBox->getChildAt(0)); - mItem = MWWorld::Ptr(); + mEnchanting.setOldItem(MWWorld::Ptr()); updateLabels(); } @@ -125,6 +154,13 @@ namespace MWGui void EnchantingDialog::onSoulSelected(MWWorld::Ptr item) { mItemSelectionDialog->setVisible(false); + mEnchanting.setSoulGem(item); + + if(mEnchanting.getGemCharge()==0) + { + mWindowManager.messageBox ("#{sNotifyMessage32}", std::vector()); + return; + } while (mSoulBox->getChildCount ()) MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); @@ -139,8 +175,6 @@ namespace MWGui image->setUserString ("ToolTipType", "ItemPtr"); image->setUserData(item); image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveSoul); - - mSoul = item; updateLabels(); } @@ -148,7 +182,7 @@ namespace MWGui { while (mSoulBox->getChildCount ()) MyGUI::Gui::getInstance ().destroyWidget (mSoulBox->getChildAt(0)); - mSoul = MWWorld::Ptr(); + mEnchanting.setSoulGem(MWWorld::Ptr()); updateLabels(); } @@ -170,4 +204,56 @@ namespace MWGui //mWindowManager.messageBox("#{sInventorySelectNoSoul}"); } + + void EnchantingDialog::notifyEffectsChanged () + { + mEffectList.mList = mEffects; + mEnchanting.setEffect(mEffectList); + updateLabels(); + } + + void EnchantingDialog::onTypeButtonClicked(MyGUI::Widget* sender) + { + mEnchanting.nextEnchantType(); + updateLabels(); + } + + void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender) + { + if (mEffects.size() <= 0) + { + mWindowManager.messageBox ("#{sNotifyMessage30}", std::vector()); + return; + } + + if (mName->getCaption ().empty()) + { + mWindowManager.messageBox ("#{sNotifyMessage10}", std::vector()); + return; + } + + if (boost::lexical_cast(mPrice->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) + { + mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector()); + return; + } + + if (mEnchanting.soulEmpty()) + { + mWindowManager.messageBox ("#{sNotifyMessage52}", std::vector()); + return; + } + + if (mEnchanting.itemEmpty()) + { + mWindowManager.messageBox ("#{sNotifyMessage11}", std::vector()); + return; + } + + mEnchanting.setNewItemName(mName->getCaption()); + mEnchanting.setEffect(mEffectList); + + mEnchanting.create(); + mWindowManager.removeGuiMode (GM_Enchanting); + } } diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index bcebb799df..60445a8dc3 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -7,6 +7,8 @@ #include "../mwbase/windowmanager.hpp" +#include "../mwmechanics/enchanting.hpp" + namespace MWGui { @@ -23,6 +25,7 @@ namespace MWGui protected: virtual void onReferenceUnavailable(); + virtual void notifyEffectsChanged (); void onCancelButtonClicked(MyGUI::Widget* sender); void onSelectItem (MyGUI::Widget* sender); @@ -34,8 +37,9 @@ namespace MWGui void onItemCancel(); void onSoulSelected(MWWorld::Ptr item); void onSoulCancel(); - + void onBuyButtonClicked(MyGUI::Widget* sender); void updateLabels(); + void onTypeButtonClicked(MyGUI::Widget* sender); ItemSelectionDialog* mItemSelectionDialog; @@ -46,15 +50,14 @@ namespace MWGui MyGUI::Button* mTypeButton; MyGUI::Button* mBuyButton; + MyGUI::TextBox* mName; MyGUI::TextBox* mEnchantmentPoints; MyGUI::TextBox* mCastCost; MyGUI::TextBox* mCharge; MyGUI::TextBox* mPrice; - MWWorld::Ptr mItem; - MWWorld::Ptr mSoul; - - float mCurrentEnchantmentPoints; + MWMechanics::Enchanting mEnchanting; + ESM::EffectList mEffectList; }; } diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 8395864521..ea91ac278f 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -72,6 +72,7 @@ namespace MWGui mMagnitudeMaxSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onMagnitudeMaxChanged); mDurationSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onDurationChanged); mAreaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &EditEffectDialog::onAreaChanged); + constantEffect=false; } void EditEffectDialog::open() @@ -164,7 +165,7 @@ namespace MWGui mMagnitudeBox->setVisible (true); curY += mMagnitudeBox->getSize().height; } - if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) + if (!(mMagicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)&&constantEffect==false) { mDurationBox->setPosition(mDurationBox->getPosition().left, curY); mDurationBox->setVisible (true); @@ -454,10 +455,13 @@ namespace MWGui mAvailableEffectsList->clear (); + int i=0; for (std::vector::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) { mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString()); + mButtonMapping[i] = *it; + ++i; } mAvailableEffectsList->adjustSize (); @@ -466,7 +470,6 @@ namespace MWGui std::string name = MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString(); MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name); - w->setUserData(*it); ToolTips::createMagicEffectToolTip (w, *it); } @@ -518,7 +521,8 @@ namespace MWGui return; } - short effectId = *sender->getUserData(); + int buttonId = *sender->getUserData(); + short effectId = mButtonMapping[buttonId]; for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) { diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index 4d27ec1c6f..8f1c071804 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -24,7 +24,7 @@ namespace MWGui void newEffect (const ESM::MagicEffect* effect); void editEffect (ESM::ENAMstruct effect); - + bool constantEffect; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Effect; EventHandle_Effect eventEffectAdded; @@ -69,7 +69,6 @@ namespace MWGui void onMagnitudeMaxChanged (MyGUI::ScrollBar* sender, size_t pos); void onDurationChanged (MyGUI::ScrollBar* sender, size_t pos); void onAreaChanged (MyGUI::ScrollBar* sender, size_t pos); - void setMagicEffect(const ESM::MagicEffect* effect); void updateBoxes(); @@ -88,6 +87,8 @@ namespace MWGui protected: + std::map mButtonMapping; // maps button ID to effect ID + Widgets::MWList* mAvailableEffectsList; MyGUI::ScrollView* mUsedEffectsView; diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp new file mode 100644 index 0000000000..d3352226b1 --- /dev/null +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -0,0 +1,164 @@ +#include "enchanting.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/manualref.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/containerstore.hpp" +namespace MWMechanics +{ + Enchanting::Enchanting(MWWorld::Ptr enchanter): + mEnchanter(enchanter), + mEnchantType(0) + {} + + void Enchanting::setOldItem(MWWorld::Ptr oldItem) + { + mOldItemPtr=oldItem; + if(!itemEmpty()) + { + mObjectType = mOldItemPtr.getTypeName(); + mOldItemId = mOldItemPtr.getCellRef().mRefID; + } + else + { + mObjectType=""; + mOldItemId=""; + } + } + + void Enchanting::setNewItemName(std::string s) + { + mNewItemName=s; + } + + void Enchanting::setEffect(ESM::EffectList effectList) + { + mEffectList=effectList; + } + + int Enchanting::getEnchantType() + { + return mEnchantType; + } + + void Enchanting::setSoulGem(MWWorld::Ptr soulGem) + { + mSoulGemPtr=soulGem; + } + + void Enchanting::create() + { + mEnchantment.mData.mCharge = getGemCharge(); + if(mEnchantType==3) + { + mEnchantment.mData.mCharge=0; + } + mEnchantment.mData.mType = mEnchantType; + mEnchantment.mData.mCost = getEnchantCost(); + mEnchantment.mEffects = mEffectList; + const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment); + + MWWorld::Ptr newobj = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); + + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobj.getCellRef().mRefID); + MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); + + mOldItemPtr.getRefData().setCount(0); + mSoulGemPtr.getRefData().setCount(0); + } + + void Enchanting::nextEnchantType() + { + mEnchantType++; + if (itemEmpty()) + { + mEnchantType = 0; + return; + } + if ((mObjectType == typeid(ESM::Armor).name())||(mObjectType == typeid(ESM::Clothing).name())) + { + switch(mEnchantType) + { + case 1: + mEnchantType = 2; + case 3: + if(getGemCharge()<400) + mEnchantType=2; + case 4: + mEnchantType = 2; + } + } + else if(mObjectType == typeid(ESM::Weapon).name()) + { + switch(mEnchantType) + { + case 3: + mEnchantType = 1; + } + } + else if(mObjectType == typeid(ESM::Book).name()) + { + mEnchantType=0; + } + } + + int Enchanting::getEnchantCost() + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + float cost = 0; + std::vector mEffects = mEffectList.mList; + int i=mEffects.size(); + for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) + { + const ESM::MagicEffect* effect = store.get().find(it->mEffectID); + + float cost1 = ((it->mMagnMin + it->mMagnMax)*it->mDuration*effect->mData.mBaseCost*0.025); + + float cost2 = (std::max(1, it->mArea)*0.125*effect->mData.mBaseCost); + + if(mEnchantType==3) + { + cost1 *= 100; + cost2 *= 2; + } + if(effect->mData.mFlags & ESM::MagicEffect::CastTarget) + cost1 *= 1.5; + + float fullcost = cost1+cost2; + fullcost*= i; + i--; + + cost+=fullcost; + } + return cost; + } + int Enchanting::getGemCharge() + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + if(soulEmpty()) + return 0; + if(mSoulGemPtr.getCellRef().mSoul=="") + return 0; + const ESM::Creature* soul = store.get().find(mSoulGemPtr.getCellRef().mSoul); + return soul->mData.mSoul; + } + + int Enchanting::getMaxEnchantValue() + { + if (itemEmpty()) + return 0; + return MWWorld::Class::get(mOldItemPtr).getEnchantmentPoints(mOldItemPtr); + } + bool Enchanting::soulEmpty() + { + if (mSoulGemPtr.isEmpty()) + return true; + return false; + } + + bool Enchanting::itemEmpty() + { + if(mOldItemPtr.isEmpty()) + return true; + return false; + } +} diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp new file mode 100644 index 0000000000..1daf34c6d1 --- /dev/null +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -0,0 +1,41 @@ +#ifndef GAME_MWMECHANICS_ENCHANTING_H +#define GAME_MWMECHANICS_ENCHANTING_H +#include +#include "../mwworld/ptr.hpp" +#include +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +namespace MWMechanics +{ + class Enchanting + { + + MWWorld::Ptr mOldItemPtr; + MWWorld::Ptr mSoulGemPtr; + MWWorld::Ptr mEnchanter; + const MWWorld::Ptr *mNewItemPtr; + int mEnchantType; + + ESM::EffectList mEffectList; + ESM::Enchantment mEnchantment; + + std::string mNewItemName; + std::string mObjectType; + std::string mOldItemId; + public: + Enchanting(MWWorld::Ptr enchanter); + void setOldItem(MWWorld::Ptr oldItem); + void setNewItemName(std::string s); + void setEffect(ESM::EffectList effectList); + void setSoulGem(MWWorld::Ptr soulGem); + void create(); + void nextEnchantType(); + int getEnchantType(); + int getEnchantCost(); + int getMaxEnchantValue(); + int getGemCharge(); + bool soulEmpty(); + bool itemEmpty(); + }; +} +#endif diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index cc20aeda75..28aa14e8e6 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -241,6 +241,11 @@ namespace MWWorld return ""; } + MWWorld::Ptr Class::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + { + throw std::runtime_error ("class can't be enchanted"); + } + MWWorld::Ptr Class::copyToCellImpl(const Ptr &ptr, CellStore &cell) const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 77c29fe489..ae75137f5f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -231,6 +231,8 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5a23aae972..81b33a55b4 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -948,6 +948,31 @@ namespace MWWorld return ret; } + const ESM::Armor *World::createRecord (const ESM::Armor& record) + { + return mStore.insert(record); + } + + const ESM::Weapon *World::createRecord (const ESM::Weapon& record) + { + return mStore.insert(record); + } + + const ESM::Clothing *World::createRecord (const ESM::Clothing& record) + { + return mStore.insert(record); + } + + const ESM::Enchantment *World::createRecord (const ESM::Enchantment& record) + { + return mStore.insert(record); + } + + const ESM::Book *World::createRecord (const ESM::Book& record) + { + return mStore.insert(record); + } + void World::update (float duration, bool paused) { mWeatherManager->update (duration); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 526e68a77a..ea318299f2 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -272,25 +272,44 @@ namespace MWWorld ///< \return Resulting mode virtual const ESM::Potion *createRecord (const ESM::Potion& record); - ///< Create a new recrod (of type potion) in the ESM store. + ///< Create a new record (of type potion) in the ESM store. /// \return pointer to created record virtual const ESM::Spell *createRecord (const ESM::Spell& record); - ///< Create a new recrod (of type spell) in the ESM store. + ///< Create a new record (of type spell) in the ESM store. /// \return pointer to created record virtual const ESM::Class *createRecord (const ESM::Class& record); - ///< Create a new recrod (of type class) in the ESM store. + ///< Create a new record (of type class) in the ESM store. /// \return pointer to created record virtual const ESM::Cell *createRecord (const ESM::Cell& record); - ///< Create a new recrod (of type cell) in the ESM store. + ///< Create a new record (of type cell) in the ESM store. /// \return pointer to created record virtual const ESM::NPC *createRecord(const ESM::NPC &record); - ///< Create a new recrod (of type npc) in the ESM store. + ///< Create a new record (of type npc) in the ESM store. /// \return pointer to created record + virtual const ESM::Armor *createRecord (const ESM::Armor& record); + ///< Create a new record (of type armor) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Weapon *createRecord (const ESM::Weapon& record); + ///< Create a new record (of type weapon) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Clothing *createRecord (const ESM::Clothing& record); + ///< Create a new record (of type clothing) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Enchantment *createRecord (const ESM::Enchantment& record); + ///< Create a new record (of type enchantment) in the ESM store. + /// \return pointer to created record + + virtual const ESM::Book *createRecord (const ESM::Book& record); + ///< Create a new record (of type book) in the ESM store. + /// \return pointer to created record virtual void update (float duration, bool paused); From eb88463b9419339bc0ba2bd8e55c16cc6b736af4 Mon Sep 17 00:00:00 2001 From: Glorf Date: Thu, 28 Mar 2013 23:39:20 +0100 Subject: [PATCH 43/47] Some enchanting fixes --- apps/openmw/mwclass/armor.cpp | 13 +++++++------ apps/openmw/mwclass/armor.hpp | 2 +- apps/openmw/mwclass/book.cpp | 13 +++++++------ apps/openmw/mwclass/book.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 13 +++++++------ apps/openmw/mwclass/clothing.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 13 +++++++------ apps/openmw/mwclass/weapon.hpp | 2 +- apps/openmw/mwmechanics/enchanting.cpp | 4 ++-- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 11 files changed, 36 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 02ed743dff..a691365747 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -274,18 +274,19 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Armor::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + MWWorld::Ptr Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - ESM::Armor oldItem = *store.get().find(ptr.getCellRef().mRefID); - ESM::Armor newItem = oldItem; + MWWorld::LiveCellRef *ref = + ptr.get(); + + ESM::Armor newItem = *ref->mBase; newItem.mId=""; newItem.mName=newName; newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return ref.getPtr(); + MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return mref.getPtr(); } boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 2c79321bb2..e987c48010 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 9714bc06e7..5e73dcfd43 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -148,19 +148,20 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Book::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + MWWorld::Ptr Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - ESM::Book oldItem = *store.get().find(ptr.getCellRef().mRefID); - ESM::Book newItem = oldItem; + MWWorld::LiveCellRef *ref = + ptr.get(); + + ESM::Book newItem = *ref->mBase; newItem.mId=""; newItem.mName=newName; newItem.mData.mIsScroll = 1; newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return ref.getPtr(); + MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return mref.getPtr(); } boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 950f2be413..b27ae78cee 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -51,7 +51,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 813746fea2..cfef27c422 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -222,18 +222,19 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Clothing::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + MWWorld::Ptr Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - ESM::Clothing oldItem = *store.get().find(ptr.getCellRef().mRefID); - ESM::Clothing newItem = oldItem; + MWWorld::LiveCellRef *ref = + ptr.get(); + + ESM::Clothing newItem = *ref->mBase; newItem.mId=""; newItem.mName=newName; newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return ref.getPtr(); + MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return mref.getPtr(); } boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index e705c113bf..d929824ffd 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,7 +59,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 79ed66a501..b17481f188 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -362,18 +362,19 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Weapon::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + MWWorld::Ptr Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - ESM::Weapon oldItem = *store.get().find(ptr.getCellRef().mRefID); - ESM::Weapon newItem = oldItem; + MWWorld::LiveCellRef *ref = + ptr.get(); + + ESM::Weapon newItem = *ref->mBase; newItem.mId=""; newItem.mName=newName; newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return ref.getPtr(); + MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); + return mref.getPtr(); } boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 24da3fe64a..561f2403f2 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index d3352226b1..2d90f62b05 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -62,8 +62,8 @@ namespace MWMechanics MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobj.getCellRef().mRefID); MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); - mOldItemPtr.getRefData().setCount(0); - mSoulGemPtr.getRefData().setCount(0); + mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); + mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); } void Enchanting::nextEnchantType() diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 28aa14e8e6..88f9d75505 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -241,7 +241,7 @@ namespace MWWorld return ""; } - MWWorld::Ptr Class::applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const + MWWorld::Ptr Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { throw std::runtime_error ("class can't be enchanted"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index ae75137f5f..2c4034616e 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -231,7 +231,7 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, std::string enchId, int enchCharge, std::string newName) const; + virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell) const; From cc8f7f238ef5a620e4103dd58c06d7aa09cc3e96 Mon Sep 17 00:00:00 2001 From: Glorf Date: Fri, 29 Mar 2013 00:55:29 +0100 Subject: [PATCH 44/47] Enchanted item base ptr fix --- apps/openmw/mwmechanics/enchanting.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 2d90f62b05..a8e23ed1fc 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -60,6 +60,7 @@ namespace MWMechanics MWWorld::Ptr newobj = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobj.getCellRef().mRefID); + newobj.mPtr = mOldItemPtr.mPtr; MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); From c5f05564511769974dffa0b7097b2072b605ce86 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Mar 2013 20:57:33 -0700 Subject: [PATCH 45/47] Handle light linear/quadratic settings --- apps/openmw/mwrender/objects.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 23d35c65f0..892b30ca14 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -271,16 +271,11 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre info.time = Ogre::Math::RangeRandom(-500, +500); info.phase = Ogre::Math::RangeRandom(-500, +500); - // changed to linear to look like morrowind - bool quadratic = false; - /* - if (!lightOutQuadInLin) - quadratic = lightQuadratic; + bool quadratic; + if (!lightOutQuadInLin()) + quadratic = lightQuadratic(); else - { quadratic = !info.interior; - } - */ if (!quadratic) { From e7684c4677c610c00c0b155e362194724dbb58fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 29 Mar 2013 09:04:02 +0100 Subject: [PATCH 46/47] some random cleanup --- apps/openmw/mwrender/objects.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 892b30ca14..5cf4abdf77 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -1,5 +1,7 @@ #include "objects.hpp" +#include + #include #include #include @@ -271,11 +273,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre info.time = Ogre::Math::RangeRandom(-500, +500); info.phase = Ogre::Math::RangeRandom(-500, +500); - bool quadratic; - if (!lightOutQuadInLin()) - quadratic = lightQuadratic(); - else - quadratic = !info.interior; + bool quadratic = lightOutQuadInLin() ? !info.interior : lightQuadratic(); if (!quadratic) { @@ -286,7 +284,7 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre else { float r = radius * lightQuadraticRadiusMult(); - float attenuation = lightQuadraticValue() / pow(r, 2); + float attenuation = lightQuadraticValue() / std::pow(r, 2); light->setAttenuation(r*10, 0, 0, attenuation); } From 86275e5bd4f0df24bb95d00abc0bace49d1383fa Mon Sep 17 00:00:00 2001 From: Glorf Date: Fri, 29 Mar 2013 12:00:09 +0100 Subject: [PATCH 47/47] Some enchanting fixes --- apps/openmw/mwclass/armor.cpp | 6 ++---- apps/openmw/mwclass/armor.hpp | 2 +- apps/openmw/mwclass/book.cpp | 6 ++---- apps/openmw/mwclass/book.hpp | 2 +- apps/openmw/mwclass/clothing.cpp | 6 ++---- apps/openmw/mwclass/clothing.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 6 ++---- apps/openmw/mwclass/weapon.hpp | 2 +- apps/openmw/mwgui/enchantingdialog.cpp | 1 + apps/openmw/mwmechanics/enchanting.cpp | 16 +++++++++------- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 12 files changed, 24 insertions(+), 29 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index a691365747..b29cbb3d11 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -16,7 +16,6 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" -#include "../mwworld/manualref.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -274,7 +273,7 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -285,8 +284,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return mref.getPtr(); + return record->mId; } boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index e987c48010..0c32015a35 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 5e73dcfd43..644561e52b 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -11,7 +11,6 @@ #include "../mwworld/actionread.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" -#include "../mwworld/manualref.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" @@ -148,7 +147,7 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -160,8 +159,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return mref.getPtr(); + return record->mId; } boost::shared_ptr Book::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index b27ae78cee..c17d4255b1 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -51,7 +51,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; ///< Generate action for using via inventory menu diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index cfef27c422..8f29a2084d 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -14,7 +14,6 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" -#include "../mwworld/manualref.hpp" #include "../mwgui/tooltips.hpp" @@ -222,7 +221,7 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -233,8 +232,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return mref.getPtr(); + return record->mId; } boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index d929824ffd..4457e79fb6 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -59,7 +59,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index b17481f188..302dc47daa 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -14,7 +14,6 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" #include "../mwworld/nullaction.hpp" -#include "../mwworld/manualref.hpp" #include "../mwgui/tooltips.hpp" @@ -362,7 +361,7 @@ namespace MWClass return ref->mBase->mEnchant; } - MWWorld::Ptr Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -373,8 +372,7 @@ namespace MWClass newItem.mData.mEnchant=enchCharge; newItem.mEnchant=enchId; const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); - MWWorld::ManualRef mref (MWBase::Environment::get().getWorld()->getStore(), record->mId); - return mref.getPtr(); + return record->mId; } boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 561f2403f2..533f32f592 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -65,7 +65,7 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 5c31a32669..6114bd4649 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -254,6 +254,7 @@ namespace MWGui mEnchanting.setEffect(mEffectList); mEnchanting.create(); + mWindowManager.messageBox ("#{sEnchantmentMenu12}", std::vector()); mWindowManager.removeGuiMode (GM_Enchanting); } } diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index a8e23ed1fc..4ef20a5e52 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -47,6 +47,9 @@ namespace MWMechanics void Enchanting::create() { + mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); + mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); + mEnchantment.mData.mCharge = getGemCharge(); if(mEnchantType==3) { @@ -57,14 +60,13 @@ namespace MWMechanics mEnchantment.mEffects = mEffectList; const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment); - MWWorld::Ptr newobj = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); + std::string newobjId = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); - MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobj.getCellRef().mRefID); - newobj.mPtr = mOldItemPtr.mPtr; - MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr()); - - mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); - mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobjId); + MWWorld::Ptr newobjPtr = ref.getPtr(); + MWWorld::Ptr result = mOldItemPtr; + result.mPtr = newobjPtr.mPtr; + MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (result); } void Enchanting::nextEnchantType() diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 88f9d75505..4af0869a31 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -241,7 +241,7 @@ namespace MWWorld return ""; } - MWWorld::Ptr Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const + std::string Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const { throw std::runtime_error ("class can't be enchanted"); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 2c4034616e..56189dafde 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -231,7 +231,7 @@ namespace MWWorld virtual std::string getModel(const MWWorld::Ptr &ptr) const; - virtual MWWorld::Ptr applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual Ptr copyToCell(const Ptr &ptr, CellStore &cell) const;