From c0b0227e8a494ea27cdc0c82df20ff4929e015d6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 16 Mar 2013 19:00:14 +0100 Subject: [PATCH 01/54] 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 fdf211c28..130c0515d 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 51c0ea21c..ff45411ed 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 dfced6daa..f5f71a776 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 f7801848f..f01c78afc 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 475c08ccb..0f6e86811 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 06cf88c5f..bf3417251 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 2b8000312..1b4a98276 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 3c8127b26..49e60aa25 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 cdcbfc4d1..d4125a05f 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 3bd67ade6..673739cbf 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 0415c9d8d..bcebb799d 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 14b1cf8ee..4b8adcef4 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 cab125f1f..733daa91a 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 71b24b65d..cc20aeda7 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 1a6a16ca0..77c29fe48 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 4ef8da0f3..c0b04618e 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 a19c56925..2549fd26f 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 11aed7474eba3aeca00cebf77ccece3c126cfa74 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 20 Mar 2013 18:34:54 +0100 Subject: [PATCH 02/54] Shadow cast on water --- files/materials/water.mat | 19 +++++++++ files/materials/water.shader | 76 +++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/files/materials/water.mat b/files/materials/water.mat index 0ec71d2df..1e5f8c8e0 100644 --- a/files/materials/water.mat +++ b/files/materials/water.mat @@ -54,5 +54,24 @@ material Water scale 0.1 0.1 alpha_op_ex source1 src_manual src_current 0.7 } + + texture_unit shadowMap0 + { + content_type shadow + tex_address_mode clamp + filtering none + } + texture_unit shadowMap1 + { + content_type shadow + tex_address_mode clamp + filtering none + } + texture_unit shadowMap2 + { + content_type shadow + tex_address_mode clamp + filtering none + } } } diff --git a/files/materials/water.shader b/files/materials/water.shader index 793cdc95e..a6d0a47e6 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -50,6 +50,13 @@ // Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html ) +#define SHADOWS_PSSM @shGlobalSettingBool(shadows_pssm) +#define SHADOWS @shGlobalSettingBool(shadows) + +#if SHADOWS || SHADOWS_PSSM + #include "shadows.h" +#endif + #define RIPPLES 1 #define REFRACTION @shGlobalSettingBool(refraction) @@ -64,6 +71,23 @@ shOutput(float4, position) shOutput(float, depthPassthrough) + +#if SHADOWS + shOutput(float4, lightSpacePos0) + shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) +#endif + +#if SHADOWS_PSSM + @shForeach(3) + shOutput(float4, lightSpacePos@shIterator) + shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator) + @shEndForeach +#endif + +#if SHADOWS || SHADOWS_PSSM + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif + SH_START_PROGRAM { shOutputPosition = shMatrixMult(wvp, shInputPosition); @@ -88,6 +112,17 @@ position = shInputPosition; depthPassthrough = shOutputPosition.z; + + +#if SHADOWS + lightSpacePos0 = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition)); +#endif +#if SHADOWS_PSSM + float4 wPos = shMatrixMult(worldMatrix, shInputPosition); + @shForeach(3) + lightSpacePos@shIterator = shMatrixMult(texViewProjMatrix@shIterator, wPos); + @shEndForeach +#endif } #else @@ -186,10 +221,47 @@ shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position_object_space) + + +#if SHADOWS + shInput(float4, lightSpacePos0) + shSampler2D(shadowMap0) + shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, 1) +#endif +#if SHADOWS_PSSM + @shForeach(3) + shInput(float4, lightSpacePos@shIterator) + shSampler2D(shadowMap@shIterator) + shUniform(float2, invShadowmapSize@shIterator) @shAutoConstant(invShadowmapSize@shIterator, inverse_texture_size, @shIterator(1)) + @shEndForeach + shUniform(float3, pssmSplitPoints) @shSharedParameter(pssmSplitPoints) +#endif + +#if SHADOWS || SHADOWS_PSSM + shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) +#endif SH_START_PROGRAM { +#if SHADOWS + float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0); +#endif +#if SHADOWS_PSSM + float shadow = pssmDepthShadow (lightSpacePos0, invShadowmapSize0, shadowMap0, lightSpacePos1, invShadowmapSize1, shadowMap1, lightSpacePos2, invShadowmapSize2, shadowMap2, depthPassthrough, pssmSplitPoints); +#endif + +#if SHADOWS || SHADOWS_PSSM + float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; + float fade = 1-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange); + shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow); +#endif + +#if !SHADOWS && !SHADOWS_PSSM + float shadow = 1.0; +#endif + + float2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; screenCoords.y = (1-shSaturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; @@ -244,7 +316,7 @@ float3 llR = reflect(lVec, pNormal); float s = shSaturate(dot(lR, vVec)*2.0-1.2); - float lightScatter = shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y)); + float lightScatter = shadow * shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y)); float3 scatterColour = shLerp(float3(SCATTER_COLOUR)*float3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); // fresnel @@ -267,7 +339,7 @@ #endif // specular - float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS); + float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS) * shadow; #if REFRACTION shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz; From 7beda509fe711190fb952ad33c784c1d1557eba3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 23 Mar 2013 09:53:38 +0100 Subject: [PATCH 03/54] Lighting should be done in view space instead of object space, so that attenuation also works correctly for scaled objects --- files/materials/objects.shader | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 46e3abeb3..ae589a05b 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -54,10 +54,11 @@ #if VERTEX_LIGHTING shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) - shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_object_space_array, @shGlobalSettingString(num_lights)) + shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) + shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix) #if VERTEXCOLOR_MODE != 2 shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) #endif @@ -131,11 +132,14 @@ #if VERTEX_LIGHTING + float3 viewPos = shMatrixMult(worldView, shInputPosition).xyz; + float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz); + float3 lightDir; float d; lightResult = float4(0,0,0,1); @shForeach(@shGlobalSettingString(num_lights)) - lightDir = lightPosition[@shIterator].xyz - (shInputPosition.xyz * lightPosition[@shIterator].w); + lightDir = lightPosition[@shIterator].xyz - (viewPos * lightPosition[@shIterator].w); d = length(lightDir); lightDir = normalize(lightDir); @@ -143,11 +147,11 @@ #if VERTEXCOLOR_MODE == 2 lightResult.xyz += colour.xyz * lightDiffuse[@shIterator].xyz * (1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) - * max(dot(normalize(normal.xyz), normalize(lightDir)), 0); + * max(dot(viewNormal.xyz, lightDir), 0); #else lightResult.xyz += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz * (1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) - * max(dot(normalize(normal.xyz), normalize(lightDir)), 0); + * max(dot(viewNormal.xyz, lightDir), 0); #endif #if @shIterator == 0 From c7275965b8c8e419eec920db231f59270bdf1059 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 13:22:06 +0100 Subject: [PATCH 04/54] added basic class record table --- apps/opencs/model/world/data.cpp | 7 +++++++ apps/opencs/model/world/data.hpp | 2 ++ apps/opencs/model/world/universalid.cpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 +++- apps/opencs/view/doc/view.cpp | 9 +++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/world/subviews.cpp | 7 +++++-- components/esm/loadclas.cpp | 14 ++++++++++++++ components/esm/loadclas.hpp | 4 ++++ 9 files changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4b10a6683..2b635d9ab 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -44,9 +44,15 @@ CSMWorld::Data::Data() mSkills.addColumn (new UseValueColumn (i)); mSkills.addColumn (new DescriptionColumn); + mClasses.addColumn (new StringIdColumn); + mClasses.addColumn (new RecordStateColumn); + mClasses.addColumn (new SpecialisationColumn); + mClasses.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); + addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); } CSMWorld::Data::~Data() @@ -122,6 +128,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; + case ESM::REC_CLAS: mClasses.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index ac953dbec..7baf03259 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -22,6 +23,7 @@ namespace CSMWorld IdCollection mGlobals; IdCollection mGmsts; IdCollection mSkills; + IdCollection mClasses; std::vector mModels; std::map mModelIndex; diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 57c276a6d..a85b30c2a 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -20,6 +20,7 @@ namespace { 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_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -29,6 +30,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_Record, CSMWorld::UniversalId::Type_Class, "Class" }, { 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 a412cb6b1..4c4d95654 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -39,7 +39,9 @@ namespace CSMWorld Type_Gmsts, Type_Gmst, Type_Skills, - Type_Skill + Type_Skill, + Type_Classes, + Type_Class }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 267ddf26c..2ef66593f 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -90,6 +90,10 @@ void CSVDoc::View::setupWorldMenu() connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView())); world->addAction (skills); + QAction *classes = new QAction (tr ("Classes"), this); + connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView())); + world->addAction (classes); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -253,6 +257,11 @@ void CSVDoc::View::addSkillsSubView() addSubView (CSMWorld::UniversalId::Type_Skills); } +void CSVDoc::View::addClassesSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Classes); +} + 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 4c5aa4078..bc8e8fc26 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -117,6 +117,8 @@ namespace CSVDoc void addGmstsSubView(); void addSkillsSubView(); + + void addClassesSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index bdff0017b..5d715ea21 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -17,6 +17,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Skills, new CSVDoc::SubViewFactoryWithCreateFlag (false)); - manager.add (CSMWorld::UniversalId::Type_Global, - new CSVDoc::SubViewFactoryWithCreateFlag (true)); + manager.add (CSMWorld::UniversalId::Type_Classes, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); + +// manager.add (CSMWorld::UniversalId::Type_Global, +// new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index a62668950..d9f367fd6 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -35,4 +35,18 @@ void Class::save(ESMWriter &esm) esm.writeHNOString("DESC", mDescription); } + void Class::blank() + { + mName.clear(); + mDescription.clear(); + + mData.mAttribute[0] = mData.mAttribute[1] = 0; + mData.mSpecialization = 0; + mData.mIsPlayable = 0; + mData.mCalc = 0; + + for (int i=0; i<5; ++i) + for (int i2=0; i2<2; ++i2) + mData.mSkills[i][i2] = 0; + } } diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 264e342e6..ac596af32 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -65,6 +65,10 @@ struct Class void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). + }; } #endif From 65cda580db62ccba881a6518d880c5027c38824a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 25 Mar 2013 14:31:46 +0100 Subject: [PATCH 05/54] added attributes to class table --- apps/opencs/model/world/columns.hpp | 53 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 3 ++ 2 files changed, 56 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 7764f5870..b41e98f40 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -285,6 +285,59 @@ namespace CSMWorld } }; + template + struct NameColumn : public Column + { + NameColumn() : Column ("Name", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mName.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mName = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct AttributesColumn : public Column + { + int mIndex; + + AttributesColumn (int index) + : Column ("Attribute #" + boost::lexical_cast (index), + ColumnBase::Display_Attribute), mIndex (index) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mAttribute[mIndex]; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mAttribute[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 2b635d9ab..b0a8b95a6 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -46,6 +46,9 @@ CSMWorld::Data::Data() mClasses.addColumn (new StringIdColumn); mClasses.addColumn (new RecordStateColumn); + mClasses.addColumn (new NameColumn); + mClasses.addColumn (new AttributesColumn (0)); + mClasses.addColumn (new AttributesColumn (1)); mClasses.addColumn (new SpecialisationColumn); mClasses.addColumn (new DescriptionColumn); From ea3b14f2d25d3174ad57d7fa7d4d7acc23e7d0ef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 26 Mar 2013 09:43:13 +0100 Subject: [PATCH 06/54] added skill columns to class --- apps/opencs/model/doc/document.cpp | 2 +- apps/opencs/model/world/columns.hpp | 46 +++++++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 4 +++ components/esm/loadskil.cpp | 7 +++-- components/esm/loadskil.hpp | 2 +- 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d1462d6a3..acca877f0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -207,7 +207,7 @@ void CSMDoc::Document::createBase() { ESM::Skill record; record.mIndex = i; - record.mId = ESM::Skill::getIndexToId (record.mIndex); + record.mId = ESM::Skill::indexToId (record.mIndex); record.blank(); getData().getSkills().add (record); diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b41e98f40..902d7d86f 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 #include "columnbase.hpp" @@ -338,6 +340,50 @@ namespace CSMWorld return true; } }; + + template + struct SkillsColumn : public Column + { + int mIndex; + bool mMajor; + + SkillsColumn (int index, bool major) + : Column ((major ? "Major Skill #" : "Minor Skill #")+ + boost::lexical_cast (index), ColumnBase::Display_String), + mIndex (index), mMajor (major) + {} + + virtual QVariant get (const Record& record) const + { + int skill = record.get().mData.mSkills[mIndex][mMajor ? 1 : 0]; + + return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + std::istringstream stream (data.toString().toUtf8().constData()); + + int index = -1; + char c; + + stream >> c >> index; + + if (index!=-1) + { + ESXRecordT record2 = record.get(); + + record2.mData.mSkills[mIndex][mMajor ? 1 : 0] = index; + + 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 b0a8b95a6..917be2632 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -50,6 +50,10 @@ CSMWorld::Data::Data() mClasses.addColumn (new AttributesColumn (0)); mClasses.addColumn (new AttributesColumn (1)); mClasses.addColumn (new SpecialisationColumn); + for (int i=0; i<5; ++i) + mClasses.addColumn (new SkillsColumn (i, true)); + for (int i=0; i<5; ++i) + mClasses.addColumn (new SkillsColumn (i, false)); mClasses.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index b9d588eef..b7259db94 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -2,6 +2,8 @@ #include +#include + #include "esmreader.hpp" #include "esmwriter.hpp" @@ -103,8 +105,9 @@ 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) - mId = getIndexToId (mIndex); + mId = indexToId (mIndex); } + void Skill::save(ESMWriter &esm) { esm.writeHNT("INDX", mIndex); @@ -120,7 +123,7 @@ void Skill::save(ESMWriter &esm) mDescription.clear(); } - std::string Skill::getIndexToId (int index) + std::string Skill::indexToId (int index) { std::ostringstream stream; diff --git a/components/esm/loadskil.hpp b/components/esm/loadskil.hpp index 83a4d8bfd..43f4fc45e 100644 --- a/components/esm/loadskil.hpp +++ b/components/esm/loadskil.hpp @@ -79,7 +79,7 @@ struct Skill void blank(); ///< Set record to default state (does not touch the ID/index). - static std::string getIndexToId (int index); + static std::string indexToId (int index); }; } #endif From 82f1cee116a740e853be87a732cfbf52dac3ec1c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 26 Mar 2013 09:51:39 +0100 Subject: [PATCH 07/54] added is-playable column to class --- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/columns.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index b5863f8e4..5c2ce8a67 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -33,7 +33,8 @@ namespace CSMWorld Display_GmstVarType, Display_GlobalVarType, Display_Specialisation, - Display_Attribute + Display_Attribute, + Display_Boolean }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 902d7d86f..cbcddd972 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -384,6 +384,31 @@ namespace CSMWorld return true; } }; + + template + struct PlayableColumn : public Column + { + PlayableColumn() : Column ("Playable", ColumnBase::Display_Boolean) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mIsPlayable!=0; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mIsPlayable = 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 917be2632..7b3e66771 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -54,6 +54,7 @@ CSMWorld::Data::Data() mClasses.addColumn (new SkillsColumn (i, true)); for (int i=0; i<5; ++i) mClasses.addColumn (new SkillsColumn (i, false)); + mClasses.addColumn (new PlayableColumn); mClasses.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); From 6f1575d42a046bff854f0a79cb834e6aaf38f4fe Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 Mar 2013 17:27:43 +0100 Subject: [PATCH 08/54] 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 521383f3f..d682cf88b 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 07e41bcfa..31ae1cfb0 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 ac27beb44..e5b68841b 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 58395d879..6616165fa 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 0731a8ff8..5cbf1de2b 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 97aa86ba0..afc953f54 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 09/54] 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 31ae1cfb0..b971fa6f3 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 10/54] 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 16e02ebba..206db51ed 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 11/54] 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 0edc18afb..7b79a8fdf 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 642291eef..041e2cc1c 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 130c0515d..02ed743df 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 ff45411ed..2c79321bb 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 4e29fa684..9714bc06e 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 acb1aac06..950f2be41 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 f5f71a776..813746fea 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 f01c78afc..e705c113b 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 0f6e86811..79ed66a50 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 bf3417251..24da3fe64 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 673739cbf..5c31a3266 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 bcebb799d..60445a8dc 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 839586452..ea91ac278 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 4d27ec1c6..8f1c07180 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 000000000..d3352226b --- /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 000000000..1daf34c6d --- /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 cc20aeda7..28aa14e8e 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 77c29fe48..ae75137f5 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 5a23aae97..81b33a55b 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 526e68a77..ea318299f 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 12/54] 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 02ed743df..a69136574 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 2c79321bb..e987c4801 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 9714bc06e..5e73dcfd4 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 950f2be41..b27ae78ce 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 813746fea..cfef27c42 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 e705c113b..d929824ff 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 79ed66a50..b17481f18 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 24da3fe64..561f2403f 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 d3352226b..2d90f62b0 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 28aa14e8e..88f9d7550 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 ae75137f5..2c4034616 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 13/54] 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 2d90f62b0..a8e23ed1f 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 14/54] 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 23d35c65f..892b30ca1 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 15/54] 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 892b30ca1..5cf4abdf7 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 16/54] 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 a69136574..b29cbb3d1 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 e987c4801..0c32015a3 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 5e73dcfd4..644561e52 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 b27ae78ce..c17d4255b 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 cfef27c42..8f29a2084 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 d929824ff..4457e79fb 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 b17481f18..302dc47da 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 561f2403f..533f32f59 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 5c31a3266..6114bd464 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 a8e23ed1f..4ef20a5e5 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 88f9d7550..4af0869a3 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 2c4034616..56189dafd 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; From a39c129954ea7cfb318f32d14644212e648a1aed Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 29 Mar 2013 19:53:52 +0100 Subject: [PATCH 17/54] Clamp individual light attenuation at 1 --- files/materials/objects.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index ae589a05b..c8616e9d1 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -146,11 +146,11 @@ #if VERTEXCOLOR_MODE == 2 lightResult.xyz += colour.xyz * lightDiffuse[@shIterator].xyz - * (1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) * max(dot(viewNormal.xyz, lightDir), 0); #else lightResult.xyz += materialDiffuse.xyz * lightDiffuse[@shIterator].xyz - * (1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) * max(dot(viewNormal.xyz, lightDir), 0); #endif From 5e7e9fd26aa2f48687e843d47ab287161b1ed82a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 29 Mar 2013 20:21:37 +0100 Subject: [PATCH 18/54] Properly calculate light activation range --- apps/openmw/mwrender/objects.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 5cf4abdf7..50c021064 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -275,17 +275,23 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre bool quadratic = lightOutQuadInLin() ? !info.interior : lightQuadratic(); + // with the standard 1 / (c + d*l + d*d*q) equation the attenuation factor never becomes zero, + // so we ignore lights if their attenuation falls below this factor. + const float threshold = 0.03; + if (!quadratic) { float r = radius * lightLinearRadiusMult(); float attenuation = lightLinearValue() / r; - light->setAttenuation(r*10, 0, attenuation, 0); + float activationRange = 1 / (threshold * attenuation); + light->setAttenuation(activationRange, 0, attenuation, 0); } else { float r = radius * lightQuadraticRadiusMult(); float attenuation = lightQuadraticValue() / std::pow(r, 2); - light->setAttenuation(r*10, 0, 0, attenuation); + float activationRange = std::sqrt(1 / (threshold * attenuation)); + light->setAttenuation(activationRange, 0, 0, attenuation); } // If there's an AttachLight bone, attach the light to that, otherwise attach it to the base scene node From 35a6ca010ae0ff99b0c3e0cae5477ccfe5f29d3a Mon Sep 17 00:00:00 2001 From: vorenon Date: Fri, 29 Mar 2013 20:43:17 +0100 Subject: [PATCH 19/54] Adjusted textbox height in race menu --- files/mygui/openmw_chargen_race.layout | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index c0b04618e..aaa5b4b50 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 @@ - + From f93cefa201e1e3cf194011e45dbe71c24e822ce5 Mon Sep 17 00:00:00 2001 From: vorenon Date: Fri, 29 Mar 2013 21:26:40 +0100 Subject: [PATCH 20/54] Changed Y position of the textboxes --- files/mygui/openmw_chargen_race.layout | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index aaa5b4b50..a27d27191 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 @@ - + From a49e52454108a591e87431797335cae83c8338c5 Mon Sep 17 00:00:00 2001 From: vorenon Date: Sat, 30 Mar 2013 03:07:34 +0100 Subject: [PATCH 21/54] Reduced width of textboxes in race menu The width of the text box was too large and MyGui didn't align the texts properly. Fixed with the help of the MyGui layout editor. --- files/mygui/openmw_chargen_race.layout | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index a27d27191..c569abb86 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 @@ - + From 04673b2f14f2572e9b2a6d5d98c066f3b778d3b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 12:54:20 +0100 Subject: [PATCH 22/54] Don't enchant if the enchantment value is too high for the item --- apps/openmw/mwgui/enchantingdialog.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 6114bd464..536dafc01 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -158,7 +158,7 @@ namespace MWGui if(mEnchanting.getGemCharge()==0) { - mWindowManager.messageBox ("#{sNotifyMessage32}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage32}"); return; } @@ -222,31 +222,37 @@ namespace MWGui { if (mEffects.size() <= 0) { - mWindowManager.messageBox ("#{sNotifyMessage30}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage30}"); return; } if (mName->getCaption ().empty()) { - mWindowManager.messageBox ("#{sNotifyMessage10}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage10}"); return; } if (boost::lexical_cast(mPrice->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) { - mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage18}"); return; } if (mEnchanting.soulEmpty()) { - mWindowManager.messageBox ("#{sNotifyMessage52}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage52}"); return; } if (mEnchanting.itemEmpty()) { - mWindowManager.messageBox ("#{sNotifyMessage11}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage11}"); + return; + } + + if (mEnchanting.getEnchantCost() > mEnchanting.getMaxEnchantValue()) + { + mWindowManager.messageBox ("#{sNotifyMessage29}"); return; } @@ -254,7 +260,7 @@ namespace MWGui mEnchanting.setEffect(mEffectList); mEnchanting.create(); - mWindowManager.messageBox ("#{sEnchantmentMenu12}", std::vector()); + mWindowManager.messageBox ("#{sEnchantmentMenu12}"); mWindowManager.removeGuiMode (GM_Enchanting); } } From e7af718b55a8a436ddc950bd47a0ebfb4a7a0e9d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 12:56:37 +0100 Subject: [PATCH 23/54] Remove unnecessary WindowManager::messageBox arguments --- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwclass/door.cpp | 2 +- apps/openmw/mwgui/alchemywindow.cpp | 12 ++++++------ apps/openmw/mwgui/container.cpp | 6 +++--- apps/openmw/mwgui/levelupdialog.cpp | 2 +- apps/openmw/mwgui/quickkeysmenu.cpp | 4 ++-- apps/openmw/mwgui/settingswindow.cpp | 4 ++-- apps/openmw/mwgui/spellcreationdialog.cpp | 12 ++++++------ apps/openmw/mwgui/spellwindow.cpp | 2 +- apps/openmw/mwgui/text_input.cpp | 4 ++-- apps/openmw/mwgui/tradewindow.cpp | 10 +++++----- apps/openmw/mwgui/trainingwindow.cpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/npcstats.cpp | 4 ++-- apps/openmw/mwscript/containerextensions.cpp | 4 ++-- apps/openmw/mwworld/actionequip.cpp | 6 +++--- apps/openmw/mwworld/failedaction.cpp | 2 +- 18 files changed, 41 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index a2d75131e..4ee95b96e 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -115,7 +115,7 @@ namespace MWClass if (needKey && hasKey) { - MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}", std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); ptr.getCellRef().mLockLevel = 0; // using a key disarms the trap ptr.getCellRef().mTrap = ""; diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index fb6329939..163cf0277 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -98,7 +98,7 @@ namespace MWClass if (needKey && hasKey) { - MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}", std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); ptr.getCellRef().mLockLevel = 0; // using a key disarms the trap ptr.getCellRef().mTrap = ""; diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index fce612600..ca7f1b913 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -77,40 +77,40 @@ namespace MWGui if (result == MWMechanics::Alchemy::Result_NoName) { - mWindowManager.messageBox("#{sNotifyMessage37}", std::vector()); + mWindowManager.messageBox("#{sNotifyMessage37}"); return; } // check if mortar & pestle is available (always needed) if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle) { - mWindowManager.messageBox("#{sNotifyMessage45}", std::vector()); + mWindowManager.messageBox("#{sNotifyMessage45}"); return; } // make sure 2 or more ingredients were selected if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients) { - mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector()); + mWindowManager.messageBox("#{sNotifyMessage6a}"); return; } if (result == MWMechanics::Alchemy::Result_NoEffects) { - mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + mWindowManager.messageBox("#{sNotifyMessage8}"); MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); return; } if (result == MWMechanics::Alchemy::Result_Success) { - mWindowManager.messageBox("#{sPotionSuccess}", std::vector()); + mWindowManager.messageBox("#{sPotionSuccess}"); MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f); } else if (result == MWMechanics::Alchemy::Result_RandomFailure) { // potion failed - mWindowManager.messageBox("#{sNotifyMessage8}", std::vector()); + mWindowManager.messageBox("#{sNotifyMessage8}"); MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f); } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 0a674ba82..98d818638 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -150,7 +150,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { // user notification "i don't buy this item" MWBase::Environment::get().getWindowManager()-> - messageBox("#{sBarterDialog4}", std::vector()); + messageBox("#{sBarterDialog4}"); return; } } @@ -294,7 +294,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) { // user notification MWBase::Environment::get().getWindowManager()-> - messageBox("#{sContentsMessage2}", std::vector()); + messageBox("#{sContentsMessage2}"); return; } @@ -318,7 +318,7 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) object.getRefData().setCount(origCount); // user notification MWBase::Environment::get().getWindowManager()-> - messageBox("#{sContentsMessage3}", std::vector()); + messageBox("#{sContentsMessage3}"); return; } diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index f0a385808..67620d49d 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -162,7 +162,7 @@ namespace MWGui MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player); if (mSpentAttributes.size() < 3) - MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}", std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}"); else { // increase attributes diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 6d51420f0..5ea13fb0d 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -291,7 +291,7 @@ namespace MWGui if (item.getRefData ().getCount() == 0) { MWBase::Environment::get().getWindowManager ()->messageBox ( - "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item), std::vector()); + "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item)); return; } @@ -317,7 +317,7 @@ namespace MWGui if (item.getRefData ().getCount() == 0) { MWBase::Environment::get().getWindowManager ()->messageBox ( - "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item), std::vector()); + "#{sQuickMenu5} " + MWWorld::Class::get(item).getName(item)); return; } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 04856c3ed..58754472d 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -362,7 +362,7 @@ namespace MWGui { std::string msg = "This resolution is not supported in Fullscreen mode. Please select a resolution from the list."; MWBase::Environment::get().getWindowManager()-> - messageBox(msg, std::vector()); + messageBox(msg); _sender->castType()->setCaption(off); } else @@ -593,7 +593,7 @@ namespace MWGui static_cast(_sender)->setCaptionWithReplacing("#{sNone}"); - MWBase::Environment::get().getWindowManager ()->messageBox ("#{sControlsMenu3}", std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox ("#{sControlsMenu3}"); MWBase::Environment::get().getWindowManager ()->disallowMouse(); MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index ea91ac278..592063a76 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -310,25 +310,25 @@ namespace MWGui { if (mEffects.size() <= 0) { - mWindowManager.messageBox ("#{sNotifyMessage30}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage30}"); return; } if (mNameEdit->getCaption () == "") { - mWindowManager.messageBox ("#{sNotifyMessage10}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage10}"); return; } if (mMagickaCost->getCaption() == "0") { - mWindowManager.messageBox ("#{sEnchantmentMenu8}", std::vector()); + mWindowManager.messageBox ("#{sEnchantmentMenu8}"); return; } if (boost::lexical_cast(mPriceLabel->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) { - mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage18}"); return; } @@ -517,7 +517,7 @@ namespace MWGui { if (mEffects.size() >= 8) { - MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage28}", std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage28}"); return; } @@ -528,7 +528,7 @@ namespace MWGui { if (it->mEffectID == effectId) { - MWBase::Environment::get().getWindowManager()->messageBox ("#{sOnetypeEffectMessage}", std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sOnetypeEffectMessage}"); return; } } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 50691d554..d7fb0e1bc 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -404,7 +404,7 @@ namespace MWGui if (spell->mData.mFlags & ESM::Spell::F_Always || spell->mData.mType == ESM::Spell::ST_Power) { - mWindowManager.messageBox("#{sDeleteSpellError}", std::vector()); + mWindowManager.messageBox("#{sDeleteSpellError}"); } else { diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index 9265cadf9..ee9144be6 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -50,7 +50,7 @@ void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) { if (mTextEdit->getCaption() == "") { - mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage37}"); MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); } else @@ -61,7 +61,7 @@ void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) { if (mTextEdit->getCaption() == "") { - mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage37}"); MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); } else diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index f84a0abc8..307533d91 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -181,7 +181,7 @@ namespace MWGui { // user notification MWBase::Environment::get().getWindowManager()-> - messageBox("#{sBarterDialog11}", std::vector()); + messageBox("#{sBarterDialog11}"); return; } @@ -190,7 +190,7 @@ namespace MWGui { // user notification MWBase::Environment::get().getWindowManager()-> - messageBox("#{sBarterDialog1}", std::vector()); + messageBox("#{sBarterDialog1}"); return; } @@ -199,7 +199,7 @@ namespace MWGui { // user notification MWBase::Environment::get().getWindowManager()-> - messageBox("#{sBarterDialog2}", std::vector()); + messageBox("#{sBarterDialog2}"); return; } @@ -209,7 +209,7 @@ namespace MWGui if (mPtr.getTypeName() != typeid(ESM::NPC).name()) { MWBase::Environment::get().getWindowManager()-> - messageBox("#{sNotifyMessage9}", std::vector()); + messageBox("#{sNotifyMessage9}"); return; } @@ -245,7 +245,7 @@ namespace MWGui if(roll > x) //trade refused { MWBase::Environment::get().getWindowManager()-> - messageBox("#{sNotifyMessage9}", std::vector()); + messageBox("#{sNotifyMessage9}"); int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt(); MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterFailDisposition); diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index ba39ee601..601b44d6c 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -129,7 +129,7 @@ namespace MWGui MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mPtr).getNpcStats (mPtr); if (npcStats.getSkill (skillId).getBase () <= pcStats.getSkill (skillId).getBase ()) { - mWindowManager.messageBox ("#{sServiceTrainingWords}", std::vector()); + mWindowManager.messageBox ("#{sServiceTrainingWords}"); return; } diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index df8a52456..09eb5c914 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -83,7 +83,7 @@ namespace MWGui if (canRest == 2) { // resting underwater or mid-air not allowed - mWindowManager.messageBox ("#{sNotifyMessage1}", std::vector()); + mWindowManager.messageBox ("#{sNotifyMessage1}"); mWindowManager.popGuiMode (); } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1480b3182..c8d87b425 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -256,7 +256,7 @@ namespace MWMechanics if(MWWorld::Class::get(iter->first).isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox( - "#{sKilledEssential}", std::vector()); + "#{sKilledEssential}"); } } diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 26c4c8e9a..51e23d16e 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -221,12 +221,12 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "")) % std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}") % static_cast (base); - MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox(message.str()); if (mLevelProgress >= 10) { // levelup is possible now - MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", std::vector()); + MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}"); } getSkill (skillIndex).setBase (base); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 81639b5be..1154b06c6 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -83,7 +83,7 @@ namespace MWScript msgBox = boost::str(boost::format(msgBox) % count % itemName); } - MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox(msgBox); } } }; @@ -179,7 +179,7 @@ namespace MWScript } if (numRemoved > 0) - MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox(msgBox); } } }; diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index eb2ae9dca..afbb505f2 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -62,7 +62,7 @@ namespace MWWorld if((*itr).mPart == ESM::PRT_Head) { if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}", std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}"); allow = false; break; @@ -90,12 +90,12 @@ namespace MWWorld if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() ) { if(it.getType() == MWWorld::ContainerStore::Type_Clothing){ // It's shoes - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}", std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}"); } else // It's boots { - MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}", std::vector()); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}"); } } break; diff --git a/apps/openmw/mwworld/failedaction.cpp b/apps/openmw/mwworld/failedaction.cpp index ec763dba0..1db00ad06 100644 --- a/apps/openmw/mwworld/failedaction.cpp +++ b/apps/openmw/mwworld/failedaction.cpp @@ -15,7 +15,7 @@ namespace MWWorld { if ( actor.getRefData().getHandle()=="player" && !(message.empty())) { - MWBase::Environment::get().getWindowManager() ->messageBox(message, std::vector()); + MWBase::Environment::get().getWindowManager() ->messageBox(message); } } } From 51204f098e77b7fc7767956045e1625eef7dbd84 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 15:51:07 +0100 Subject: [PATCH 24/54] Added soulgem dialog; made interactive message boxes not close the previous UI --- apps/openmw/CMakeLists.txt | 4 +-- apps/openmw/mwbase/windowmanager.hpp | 3 +++ apps/openmw/mwclass/misc.cpp | 10 ++++++++ apps/openmw/mwclass/misc.hpp | 4 +++ apps/openmw/mwgui/enchantingdialog.cpp | 5 ++++ apps/openmw/mwgui/enchantingdialog.hpp | 1 + apps/openmw/mwgui/messagebox.cpp | 21 ++++++++------- apps/openmw/mwgui/messagebox.hpp | 9 ++++++- apps/openmw/mwgui/mode.hpp | 4 +-- apps/openmw/mwgui/soulgemdialog.cpp | 34 +++++++++++++++++++++++++ apps/openmw/mwgui/soulgemdialog.hpp | 28 ++++++++++++++++++++ apps/openmw/mwgui/windowmanagerimp.cpp | 29 +++++++++++++-------- apps/openmw/mwgui/windowmanagerimp.hpp | 7 +++++ apps/openmw/mwinput/inputmanagerimp.cpp | 8 +++--- apps/openmw/mwworld/actionsoulgem.cpp | 21 +++++++++++++++ apps/openmw/mwworld/actionsoulgem.hpp | 19 ++++++++++++++ 16 files changed, 177 insertions(+), 30 deletions(-) create mode 100644 apps/openmw/mwgui/soulgemdialog.cpp create mode 100644 apps/openmw/mwgui/soulgemdialog.hpp create mode 100644 apps/openmw/mwworld/actionsoulgem.cpp create mode 100644 apps/openmw/mwworld/actionsoulgem.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9b1e5a02f..41f56f993 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 repair + merchantrepair repair soulgemdialog ) 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 actionrepair + esmstore store recordcmp fallback actionrepair actionsoulgem ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 6760c89d0..58897dc74 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -237,10 +237,13 @@ namespace MWBase virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0; + virtual void startSelfEnchanting(MWWorld::Ptr soulgem) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; virtual void startRepair(MWWorld::Ptr actor) = 0; virtual void startRepairItem(MWWorld::Ptr item) = 0; + virtual void showSoulgemDialog (MWWorld::Ptr item) = 0; + virtual void changePointer (const std::string& name) = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index b971fa6f3..b8a928bec 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -15,6 +15,7 @@ #include "../mwworld/physicssystem.hpp" #include "../mwworld/manualref.hpp" #include "../mwworld/nullaction.hpp" +#include "../mwworld/actionsoulgem.hpp" #include "../mwgui/tooltips.hpp" @@ -233,4 +234,13 @@ namespace MWClass } return newPtr; } + + boost::shared_ptr Miscellaneous::use (const MWWorld::Ptr& ptr) const + { + if (ptr.getCellRef().mSoul == "") + return boost::shared_ptr(new MWWorld::NullAction()); + else + return boost::shared_ptr(new MWWorld::ActionSoulgem(ptr)); + } + } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index a5a79a8f6..12a50af19 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -49,6 +49,10 @@ 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 }; } diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 536dafc01..ef124bb43 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -92,6 +92,11 @@ namespace MWGui startEditing (); } + void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) + { + /// \todo + } + void EnchantingDialog::onReferenceUnavailable () { mWindowManager.removeGuiMode (GM_Dialogue); diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 60445a8dc..347b37e90 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -22,6 +22,7 @@ namespace MWGui virtual void open(); void startEnchanting(MWWorld::Ptr actor); + void startSelfEnchanting(MWWorld::Ptr soulgem); protected: virtual void onReferenceUnavailable(); diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index b8a34c457..46663b67a 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -3,6 +3,7 @@ #include "messagebox.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwbase/inputmanager.hpp" using namespace MWGui; @@ -62,7 +63,8 @@ void MessageBoxManager::onFrame (float frameDuration) if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { delete mInterMessageBoxe; mInterMessageBoxe = NULL; - mWindowManager->removeGuiMode(GM_InterMessageBox); + MWBase::Environment::get().getInputManager()->changeInputMode( + MWBase::Environment::get().getWindowManager()->isGuiMode()); } } @@ -90,11 +92,8 @@ void MessageBoxManager::createMessageBox (const std::string& message) bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector& buttons) { - /// \todo Don't write this kind of error message to cout. Either discard the old message box - /// silently or throw an exception. if(mInterMessageBoxe != NULL) { - std::cout << "there is a MessageBox already" << std::endl; - return false; + throw std::runtime_error("There is a message box already"); } mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons); @@ -139,7 +138,8 @@ void MessageBoxManager::setMessageBoxSpeed (int speed) void MessageBoxManager::enterPressed () { - mInterMessageBoxe->enterPressed(); + if(mInterMessageBoxe != NULL) + mInterMessageBoxe->enterPressed(); } int MessageBoxManager::readPressedButton () @@ -213,10 +213,12 @@ int MessageBox::getHeight () InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons) - : Layout("openmw_interactive_messagebox.layout") + : WindowModal("openmw_interactive_messagebox.layout", *MWBase::Environment::get().getWindowManager()) , mMessageBoxManager(parMessageBoxManager) , mButtonPressed(-1) { + WindowModal::open(); + int fixedWidth = 500; int textPadding = 10; // padding between text-widget and main-widget int textButtonPadding = 20; // padding between the text-widget und the button-widget @@ -232,7 +234,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan getWidget(mButtonsWidget, "buttons"); mMessageWidget->setOverflowToTheLeft(true); - mMessageWidget->addText(message); + mMessageWidget->setCaptionWithReplacing(message); MyGUI::IntSize textSize = mMessageWidget->getTextSize(); @@ -252,7 +254,7 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan std::string("MW_Button"), dummyCoord, MyGUI::Align::Default); - button->setCaption(*it); + button->setCaptionWithReplacing(*it); button->eventMouseButtonClick += MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed); @@ -399,6 +401,7 @@ void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed) if(*button == pressed) { mButtonPressed = index; + mMessageBoxManager.onButtonPressed(mButtonPressed); return; } index++; diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 149aa7e7f..859e1806a 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -44,6 +44,13 @@ namespace MWGui void enterPressed(); int readPressedButton (); + typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Int; + + // Note: this delegate unassigns itself after it was fired, i.e. works once. + EventHandle_Int eventButtonPressed; + + void onButtonPressed(int button) { eventButtonPressed(button); eventButtonPressed.clear(); } + MWBase::WindowManager *mWindowManager; private: @@ -73,7 +80,7 @@ namespace MWGui int mNextBoxPadding; }; - class InteractiveMessageBox : public OEngine::GUI::Layout + class InteractiveMessageBox : public WindowModal { public: InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons); diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 4091f47ac..e9b01395f 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -5,6 +5,7 @@ namespace MWGui { enum GuiMode { + GM_None, GM_Settings, // Settings window GM_Inventory, // Inventory mode GM_Container, @@ -41,9 +42,6 @@ namespace MWGui GM_ClassCreate, GM_Review, - // interactive MessageBox - GM_InterMessageBox, - GM_Loading, GM_LoadingWallpaper, diff --git a/apps/openmw/mwgui/soulgemdialog.cpp b/apps/openmw/mwgui/soulgemdialog.cpp new file mode 100644 index 000000000..4530a13d0 --- /dev/null +++ b/apps/openmw/mwgui/soulgemdialog.cpp @@ -0,0 +1,34 @@ +#include "soulgemdialog.hpp" + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/environment.hpp" + +#include "messagebox.hpp" + +namespace MWGui +{ + + void SoulgemDialog::show(const MWWorld::Ptr &soulgem) + { + mSoulgem = soulgem; + std::vector buttons; + buttons.push_back("#{sRechargeEnchantment}"); + buttons.push_back("#{sMake Enchantment}"); + mManager->createInteractiveMessageBox("#{sDoYouWantTo}", buttons); + mManager->eventButtonPressed += MyGUI::newDelegate(this, &SoulgemDialog::onButtonPressed); + } + + void SoulgemDialog::onButtonPressed(int button) + { + if (button == 0) + { + /// \todo show recharge enchanted item dialog here + } + else + { + MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting); + MWBase::Environment::get().getWindowManager()->startSelfEnchanting(mSoulgem); + } + } + +} diff --git a/apps/openmw/mwgui/soulgemdialog.hpp b/apps/openmw/mwgui/soulgemdialog.hpp new file mode 100644 index 000000000..9aea1f339 --- /dev/null +++ b/apps/openmw/mwgui/soulgemdialog.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_MWGUI_SOULGEMDIALOG_H +#define OPENMW_MWGUI_SOULGEMDIALOG_H + +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + + class MessageBoxManager; + + class SoulgemDialog + { + public: + SoulgemDialog (MessageBoxManager* manager) + : mManager(manager) {} + + void show (const MWWorld::Ptr& soulgem); + + void onButtonPressed(int button); + + private: + MessageBoxManager* mManager; + MWWorld::Ptr mSoulgem; + }; + +} + +#endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 718bb7106..eadd65787 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -57,6 +57,7 @@ #include "spellicons.hpp" #include "merchantrepair.hpp" #include "repair.hpp" +#include "soulgemdialog.hpp" using namespace MWGui; @@ -94,6 +95,7 @@ WindowManager::WindowManager( , mTrainingWindow(NULL) , mMerchantRepair(NULL) , mRepair(NULL) + , mSoulgemDialog(NULL) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -186,6 +188,7 @@ WindowManager::WindowManager( mTrainingWindow = new TrainingWindow(*this); mMerchantRepair = new MerchantRepair(*this); mRepair = new Repair(*this); + mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -253,6 +256,7 @@ WindowManager::~WindowManager() delete mQuickKeysMenu; delete mMerchantRepair; delete mRepair; + delete mSoulgemDialog; delete mCursor; cleanupGarbage(); @@ -316,9 +320,6 @@ void WindowManager::updateVisible() mHud->setVisible(mHudEnabled); - // Mouse is visible whenever we're not in game mode - mCursor->setVisible(isGuiMode()); - bool gameMode = !isGuiMode(); mInputBlocker->setVisible (gameMode); @@ -444,8 +445,6 @@ void WindowManager::updateVisible() case GM_Repair: mRepair->setVisible(true); break; - case GM_InterMessageBox: - break; case GM_Journal: mJournal->setVisible(true); break; @@ -609,7 +608,7 @@ void WindowManager::messageBox (const std::string& message, const std::vectorcreateInteractiveMessageBox(message, buttons); - pushGuiMode(GM_InterMessageBox); + MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode()); } } @@ -648,6 +647,7 @@ void WindowManager::onDialogueWindowBye() void WindowManager::onFrame (float frameDuration) { mMessageBoxManager->onFrame(frameDuration); + mToolTips->onFrame(frameDuration); if (mDragAndDrop->mIsOnDragAndDrop) @@ -1033,12 +1033,12 @@ void WindowManager::toggleVisible (GuiWindow wnd) bool WindowManager::isGuiMode() const { - return !mGuiModes.empty(); + return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox(); } bool WindowManager::isConsoleMode() const { - if (mGuiModes.back()==GM_Console) + if (!mGuiModes.empty() && mGuiModes.back()==GM_Console) return true; return false; } @@ -1046,8 +1046,7 @@ bool WindowManager::isConsoleMode() const MWGui::GuiMode WindowManager::getMode() const { if (mGuiModes.empty()) - throw std::runtime_error ("getMode() called, but there is no active mode"); - + return GM_None; return mGuiModes.back(); } @@ -1143,6 +1142,11 @@ void WindowManager::startEnchanting (MWWorld::Ptr actor) mEnchantingDialog->startEnchanting (actor); } +void WindowManager::startSelfEnchanting(MWWorld::Ptr soulgem) +{ + mEnchantingDialog->startSelfEnchanting(soulgem); +} + void WindowManager::startTraining(MWWorld::Ptr actor) { mTrainingWindow->startTraining(actor); @@ -1167,3 +1171,8 @@ void WindowManager::changePointer(const std::string &name) { mCursor->onCursorChange(name); } + +void WindowManager::showSoulgemDialog(MWWorld::Ptr item) +{ + mSoulgemDialog->show(item); +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 216ab9a6f..5cf7bae02 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -76,6 +76,7 @@ namespace MWGui class SpellIcons; class MerchantRepair; class Repair; + class SoulgemDialog; class WindowManager : public MWBase::WindowManager { @@ -230,14 +231,19 @@ namespace MWGui virtual void startSpellMaking(MWWorld::Ptr actor); virtual void startEnchanting(MWWorld::Ptr actor); + virtual void startSelfEnchanting(MWWorld::Ptr soulgem); virtual void startTraining(MWWorld::Ptr actor); virtual void startRepair(MWWorld::Ptr actor); virtual void startRepairItem(MWWorld::Ptr item); + virtual void showSoulgemDialog (MWWorld::Ptr item); + virtual void changePointer (const std::string& name); virtual const Translation::Storage& getTranslationDataStorage() const; + void onSoulgemDialogButtonPressed (int button); + private: OEngine::GUI::MyGUIManager *mGuiManager; OEngine::Render::OgreRenderer *mRendering; @@ -271,6 +277,7 @@ namespace MWGui EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; MerchantRepair* mMerchantRepair; + SoulgemDialog* mSoulgemDialog; Repair* mRepair; Translation::Storage& mTranslationDataStorage; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index f49422747..bd5367dad 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -181,8 +181,7 @@ namespace MWInput break; case A_Activate: resetIdleTime(); - if( MWBase::Environment::get().getWindowManager()->isGuiMode() - && MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox ) { + if( MWBase::Environment::get().getWindowManager()->isGuiMode()) { // Pressing the activation key when a messagebox is prompting for "ok" will activate the ok button MWBase::Environment::get().getWindowManager()->enterPressed(); } @@ -378,7 +377,7 @@ namespace MWInput void InputManager::changeInputMode(bool guiMode) { - // Are we in GUI mode now? + MWBase::Environment::get().getWindowManager()->setMouseVisible(guiMode); if(guiMode) { // Disable mouse look @@ -462,8 +461,7 @@ namespace MWInput bool InputManager::keyPressed( const OIS::KeyEvent &arg ) { if(arg.key == OIS::KC_RETURN - && MWBase::Environment::get().getWindowManager()->isGuiMode() - && MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox ) + && MWBase::Environment::get().getWindowManager()->isGuiMode()) { // Pressing enter when a messagebox is prompting for "ok" will activate the ok button MWBase::Environment::get().getWindowManager()->enterPressed(); diff --git a/apps/openmw/mwworld/actionsoulgem.cpp b/apps/openmw/mwworld/actionsoulgem.cpp new file mode 100644 index 000000000..6746f692f --- /dev/null +++ b/apps/openmw/mwworld/actionsoulgem.cpp @@ -0,0 +1,21 @@ +#include "actionsoulgem.hpp" + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/environment.hpp" + +namespace MWWorld +{ + +ActionSoulgem::ActionSoulgem(const Ptr &object) + : Action(false, object) +{ + +} + +void ActionSoulgem::executeImp(const Ptr &actor) +{ + MWBase::Environment::get().getWindowManager()->showSoulgemDialog(getTarget()); +} + + +} diff --git a/apps/openmw/mwworld/actionsoulgem.hpp b/apps/openmw/mwworld/actionsoulgem.hpp new file mode 100644 index 000000000..0dd526657 --- /dev/null +++ b/apps/openmw/mwworld/actionsoulgem.hpp @@ -0,0 +1,19 @@ +#ifndef GAME_MWWORLD_ACTIONSOULGEM_H +#define GAME_MWWORLD_ACTIONSOULGEM_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class ActionSoulgem : public Action + { + virtual void executeImp (const MWWorld::Ptr& actor); + + public: + /// @param soulgem to use + ActionSoulgem (const Ptr& object); + }; +} + +#endif From a031c7761943afc38df5e0ea2a595a3cdcc4d90f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 15:56:14 +0100 Subject: [PATCH 25/54] Improved enchanting layout --- files/mygui/openmw_enchanting_dialog.layout | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/files/mygui/openmw_enchanting_dialog.layout b/files/mygui/openmw_enchanting_dialog.layout index 2549fd26f..41b8ffa93 100644 --- a/files/mygui/openmw_enchanting_dialog.layout +++ b/files/mygui/openmw_enchanting_dialog.layout @@ -70,18 +70,18 @@ - + - + - + - - + + From 0079f62180afe7ddf2f9ec3f2d543bca07ee2891 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 16:27:06 +0100 Subject: [PATCH 26/54] Gold condition now always checks RefID instead of the name. This is necessary because in the french MW version, the sGold GMST is different from the name of the gold references. --- apps/openmw/mwclass/misc.cpp | 7 ++++- apps/openmw/mwworld/containerstore.cpp | 38 +++++++++++--------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index b971fa6f3..e4d7235cb 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -158,7 +158,12 @@ namespace MWClass int count = ptr.getRefData().getCount(); - bool isGold = (ref->mBase->mName == store.get().find("sGold")->getString()); + bool isGold = Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); + if (isGold && ptr.getCellRef().mGoldValue != 1) count = ptr.getCellRef().mGoldValue; else if (isGold) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index e5b68841b..a377f2bbb 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -111,34 +111,28 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr) // gold needs special handling: when it is inserted into a container, the base object automatically becomes Gold_001 // this ensures that gold piles of different sizes stack with each other (also, several scripts rely on Gold_001 for detecting player gold) - if (MWWorld::Class::get(ptr).getName(ptr) == esmStore.get().find("sGold")->getString()) + if (Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100")) { - MWWorld::LiveCellRef *gold = - ptr.get(); + MWWorld::ManualRef ref(esmStore, "Gold_001"); - 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")) + 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) { - MWWorld::ManualRef ref(esmStore, "Gold_001"); - - 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) + if (Misc::StringUtils::ciEqual((*iter).get()->mRef.mRefID, "gold_001")) { - if (Misc::StringUtils::ciEqual((*iter).get()->mRef.mRefID, "gold_001")) - { - (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); - flagAsModified(); - return iter; - } + (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); + flagAsModified(); + return iter; } - - return addImpl(ref.getPtr()); } + + return addImpl(ref.getPtr()); } // determine whether to stack or not From a723ad8f291c532bbb33fffb4193f44395d4c845 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 16:32:24 +0100 Subject: [PATCH 27/54] Don't allow toggling inventory or journal when a modal window is opened --- apps/openmw/mwinput/inputmanagerimp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index f49422747..013c722c0 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -623,6 +623,9 @@ namespace MWInput void InputManager::toggleInventory() { + if (MyGUI::InputManager::getInstance ().isModalAny()) + return; + bool gameMode = !mWindows.isGuiMode(); // Toggle between game mode and inventory mode @@ -660,6 +663,9 @@ namespace MWInput void InputManager::toggleJournal() { + if (MyGUI::InputManager::getInstance ().isModalAny()) + return; + // Toggle between game mode and journal mode bool gameMode = !mWindows.isGuiMode(); From 0f0cc0e3e301c73a80dbe446b31b4d68bd8d5602 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 18:29:21 +0100 Subject: [PATCH 28/54] Fix a few gold conditions that I missed, trade window was affected --- apps/openmw/mwclass/misc.cpp | 42 +++++++++++++++---------------- apps/openmw/mwgui/container.cpp | 4 +-- apps/openmw/mwgui/tradewindow.cpp | 5 +++- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index e4d7235cb..c1639af2b 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -23,6 +23,18 @@ #include +namespace +{ +bool isGold (const MWWorld::Ptr& ptr) +{ + return Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); +} +} + namespace MWClass { void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -109,25 +121,15 @@ namespace MWClass std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) - { + if (isGold(ptr)) return std::string("Item Gold Up"); - } return std::string("Item Misc Up"); } std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) - { + if (isGold(ptr)) return std::string("Item Gold Down"); - } return std::string("Item Misc Down"); } @@ -158,19 +160,15 @@ namespace MWClass int count = ptr.getRefData().getCount(); - bool isGold = Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); + bool gold = isGold(ptr); - if (isGold && ptr.getCellRef().mGoldValue != 1) + if (gold && ptr.getCellRef().mGoldValue != 1) count = ptr.getCellRef().mGoldValue; - else if (isGold) + else if (gold) count *= ref->mBase->mData.mValue; std::string countString; - if (!isGold) + if (!gold) countString = MWGui::ToolTips::getCountString(count); else // gold displays its count also if it's 1. countString = " (" + boost::lexical_cast(count) + ")"; @@ -186,7 +184,7 @@ namespace MWClass std::string text; - if (!isGold) + if (!gold) { text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); @@ -210,7 +208,7 @@ namespace MWClass const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - if (MWWorld::Class::get(ptr).getName(ptr) == store.get().find("sGold")->getString()) { + if (isGold(ptr)) { int goldAmount = ptr.getRefData().getCount(); std::string base = "Gold_001"; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 0a674ba82..36e32c822 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -144,9 +144,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) MWBase::Environment::get().getWorld()->getStore().get(); // the player is trying to sell an item, check if the merchant accepts it - // also, don't allow selling gold (let's be better than Morrowind at this, can we?) - if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object) || - MWWorld::Class::get(object).getName(object) == gmst.find("sGold")->getString()) + if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) { // user notification "i don't buy this item" MWBase::Environment::get().getWindowManager()-> diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index f84a0abc8..f474f756d 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -135,7 +135,7 @@ namespace MWGui for (MWWorld::ContainerStoreIterator it = playerStore.begin(); it != playerStore.end(); ++it) { - if (MWWorld::Class::get(*it).getName(*it) == gmst.find("sGold")->getString()) + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001")) { goldFound = true; gold = *it; @@ -342,6 +342,9 @@ namespace MWGui bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) { + if (Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")) + return false; + int services = 0; if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { From ee5d0277e8729965bbce2efc0e9b4db3448e3cba Mon Sep 17 00:00:00 2001 From: lazydev Date: Sat, 30 Mar 2013 22:18:34 +0400 Subject: [PATCH 29/54] fix for #634 --- apps/openmw/mwdialogue/filter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index cd9908d3d..f7e952956 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -198,7 +198,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c if (imData.mNumLongs) return select.selectCompare (locals.mLongs[i]); - i -= script->mData.mNumShorts; + i -= script->mData.mNumLongs; return select.selectCompare (locals.mFloats.at (i)); } From e27e53f607550f65c6b7b962fc5151f20b2d7101 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 20:04:05 +0100 Subject: [PATCH 30/54] Fix not playable body parts appearing in the race selection menu. --- apps/esmtool/labels.cpp | 4 +- apps/openmw/mwgui/container.cpp | 3 - apps/openmw/mwgui/race.cpp | 138 ++++++++++++++++++++---------- apps/openmw/mwgui/race.hpp | 3 + apps/openmw/mwgui/tradewindow.cpp | 3 - components/esm/loadbody.hpp | 2 +- 6 files changed, 99 insertions(+), 54 deletions(-) diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index f08c31003..3fb1166e8 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags) std::string properties = ""; if (flags == 0) properties += "[None] "; if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; - if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable "; + if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; int unused = (0xFFFFFFFF ^ (ESM::BodyPart::BPF_Female| - ESM::BodyPart::BPF_Playable)); + ESM::BodyPart::BPF_NotPlayable)); if (flags & unused) properties += "Invalid "; properties += str(boost::format("(0x%08X)") % flags); return properties; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 36e32c822..7836fee16 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -140,9 +140,6 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) if (isInventory()) { - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - // the player is trying to sell an item, check if the merchant accepts it if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) { diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 1436995c5..be693eb2b 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -19,6 +19,49 @@ using namespace MWGui; using namespace Widgets; +namespace +{ +int wrap(int index, int max) +{ + if (index < 0) + return max - 1; + else if (index >= max) + return 0; + else + return index; +} + +int countParts(const std::string &part, const std::string &race, bool male) +{ + /// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs + const MWWorld::Store &store = + MWBase::Environment::get().getWorld()->getStore().get(); + + std::string prefix = + "b_n_" + race + ((male) ? "_m_" : "_f_") + part; + + std::string suffix; + suffix.reserve(prefix.size() + 3); + + int count = -1; + do { + ++count; + suffix = "_" + (boost::format("%02d") % (count + 1)).str(); + } + while (store.search(prefix + suffix) != 0); + + if (count == 0 && part == "hair") { + count = -1; + do { + ++count; + suffix = (boost::format("%02d") % (count + 1)).str(); + } + while (store.search(prefix + suffix) != 0); + } + return count; +} +} + RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) : WindowModal("openmw_chargen_race.layout", parWindowManager) , mGenderIndex(0) @@ -144,45 +187,6 @@ void RaceDialog::setRaceId(const std::string &raceId) updateSpellPowers(); } -int wrap(int index, int max) -{ - if (index < 0) - return max - 1; - else if (index >= max) - return 0; - else - return index; -} - -int countParts(const std::string &part, const std::string &race, bool male) -{ - const MWWorld::Store &store = - MWBase::Environment::get().getWorld()->getStore().get(); - - std::string prefix = - "b_n_" + race + ((male) ? "_m_" : "_f_") + part; - - std::string suffix; - suffix.reserve(prefix.size() + 3); - - int count = -1; - do { - ++count; - suffix = "_" + (boost::format("%02d") % (count + 1)).str(); - } - while (store.search(prefix + suffix) != 0); - - if (count == 0 && part == "hair") { - count = -1; - do { - ++count; - suffix = (boost::format("%02d") % (count + 1)).str(); - } - while (store.search(prefix + suffix) != 0); - } - return count; -} - void RaceDialog::close() { delete mPreview; @@ -229,28 +233,67 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*) void RaceDialog::onSelectPreviousFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectNextFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectPreviousHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex - 1, mHairCount); + do + mHairIndex = wrap(mHairIndex - 1, mHairCount); + while (!isHairPlayable()); updatePreview(); } void RaceDialog::onSelectNextHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex + 1, mHairCount); + do + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isHairPlayable()); updatePreview(); } +bool RaceDialog::isFacePlayable() +{ + std::string prefix = + "b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_"); + + std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str(); + + const MWWorld::Store &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + + if (parts.search(prefix + "head_" + headIndex) == 0) + return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); + else + return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); +} + +bool RaceDialog::isHairPlayable() +{ + std::string prefix = + "b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_"); + + std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str(); + + const MWWorld::Store &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + if (parts.search(prefix + "hair_" + hairIndex) == 0) + return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); + else + return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); +} + void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) { if (_index == MyGUI::ITEM_NONE) @@ -273,11 +316,16 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) void RaceDialog::recountParts() { + mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); + mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + mFaceIndex = 0; mHairIndex = 0; - mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); - mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + while (!isHairPlayable()) + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isFacePlayable()) + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); } // update widget content diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index efd08f439..0ca440ad5 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -81,6 +81,9 @@ namespace MWGui void updatePreview(); void recountParts(); + bool isHairPlayable(); + bool isFacePlayable(); + MyGUI::ImageBox* mPreviewImage; MyGUI::ListBox* mRaceList; MyGUI::ScrollBar* mHeadRotate; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index f474f756d..ab9f3a310 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -129,9 +129,6 @@ namespace MWGui MWWorld::Ptr gold; MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore(); - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - for (MWWorld::ContainerStoreIterator it = playerStore.begin(); it != playerStore.end(); ++it) { diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index c91bb40bf..c467b3625 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -33,7 +33,7 @@ struct BodyPart enum Flags { BPF_Female = 1, - BPF_Playable = 2 + BPF_NotPlayable = 2 }; enum MeshType From c8606d2f63d63c8db1cca9838d2f03466587907f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 30 Mar 2013 13:20:51 -0700 Subject: [PATCH 31/54] Implement IsWerewolf script function --- apps/openmw/mwscript/docs/vmformat.txt | 4 +++- apps/openmw/mwscript/statsextensions.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 0f07b4d2e..7e9827062 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -316,5 +316,7 @@ op 0x20001f9: Drop, explicit reference op 0x20001fa: DropSoulGem op 0x20001fb: DropSoulGem, explicit reference op 0x20001fc: OnDeath +op 0x20001fd: IsWerewolf +op 0x20001fe: IsWerewolf, explicit reference -opcodes 0x20001fd-0x3ffffff unused +opcodes 0x20001ff-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index c5fc9436b..1d321fbbb 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1046,6 +1046,18 @@ namespace MWScript } }; + template + class OpIsWerewolf : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push(MWWorld::Class::get(ptr).getNpcStats(ptr).isWerewolf()); + } + }; + const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; @@ -1137,6 +1149,9 @@ namespace MWScript const int opcodeOnDeath = 0x20001fc; + const int opcodeIsWerewolf = 0x20001fd; + const int opcodeIsWerewolfExplicit = 0x20001fe; + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -1252,6 +1267,8 @@ namespace MWScript extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit); extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath); + + extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -1368,6 +1385,9 @@ namespace MWScript interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank); interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath); + + interpreter.installSegment5 (opcodeIsWerewolf, new OpIsWerewolf); + interpreter.installSegment5 (opcodeIsWerewolfExplicit, new OpIsWerewolf); } } } From 63af72c31577454322524c30982f964e4b6cfaa3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 30 Mar 2013 17:31:16 -0700 Subject: [PATCH 32/54] Avoid converting to and from quaternions --- apps/openmw/mwrender/renderingmanager.cpp | 34 +++++++++-------------- apps/openmw/mwworld/worldimp.cpp | 4 ++- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 1bab676c3..7c442c686 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -262,37 +262,29 @@ void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3 ptr.getRefData().getBaseNode()->setScale(scale); } -bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust) +bool RenderingManager::rotateObject(const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust) { bool isActive = ptr.getRefData().getBaseNode() != 0; bool isPlayer = isActive && ptr.getRefData().getHandle() == "player"; bool force = true; - + if (isPlayer) force = mPlayer->rotate(rot, adjust); - - MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); + MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); if (!isPlayer && isActive) { - Ogre::Quaternion xr(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yr(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); - - Ogre::Quaternion xref(Ogre::Radian(-ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); - - Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; - - Ogre::Matrix3 mat; - newo.ToRotationMatrix(mat); - Ogre::Radian ax,ay,az; - mat.ToEulerAnglesXYZ(ax,ay,az); - rot.x = -ax.valueRadians(); - rot.y = -ay.valueRadians(); - rot.z = -az.valueRadians(); + if(adjust) + { + const float *objRot = ptr.getRefData().getPosition().rot; + rot.x += objRot[0]; + rot.y += objRot[1]; + rot.z += objRot[2]; + } + Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X) * + Ogre::Quaternion(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y) * + Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); ptr.getRefData().getBaseNode()->setOrientation(newo); } else if(isPlayer) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 75ff6ec83..209e4c4be 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -816,7 +816,9 @@ namespace MWWorld { // rotate physically iff renderer confirm so float *objRot = ptr.getRefData().getPosition().rot; - objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; + objRot[0] = rot.x; + objRot[1] = rot.y; + objRot[2] = rot.z; if (ptr.getRefData().getBaseNode() != 0) { mPhysics->rotateObject(ptr); From af65ecd8415b3504c26b8d9fdb8d713bfef2fa89 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 30 Mar 2013 18:37:40 -0700 Subject: [PATCH 33/54] Pass the movement vector in as a parameter to CharacterController::update --- apps/openmw/mwmechanics/activators.cpp | 5 ++++- apps/openmw/mwmechanics/actors.cpp | 3 ++- apps/openmw/mwmechanics/character.cpp | 6 +----- apps/openmw/mwmechanics/character.hpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/activators.cpp b/apps/openmw/mwmechanics/activators.cpp index b67fcb216..51fa55f4e 100644 --- a/apps/openmw/mwmechanics/activators.cpp +++ b/apps/openmw/mwmechanics/activators.cpp @@ -56,7 +56,10 @@ void Activators::update(float duration, bool paused) if(!paused) { for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter) - iter->second.update(duration); + { + Ogre::Vector3 movement(0.0f); + iter->second.update(duration, movement); + } } } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1480b3182..a7615311b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -266,7 +266,8 @@ namespace MWMechanics for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { - Ogre::Vector3 movement = iter->second.update(duration); + Ogre::Vector3 movement(0.0f); + iter->second.update(duration, movement); mMovement.push_back(std::make_pair(iter->first, movement)); } MWBase::Environment::get().getWorld()->doPhysics(mMovement, duration); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 62958db8d..5e112d54e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -168,10 +168,8 @@ void CharacterController::markerEvent(float time, const std::string &evt) } -Ogre::Vector3 CharacterController::update(float duration) +void CharacterController::update(float duration, Ogre::Vector3 &movement) { - Ogre::Vector3 movement(0.0f); - float speed = 0.0f; if(!(getState() >= CharState_Death1)) { @@ -240,8 +238,6 @@ Ogre::Vector3 CharacterController::update(float duration) movement += mAnimation->runAnimation(duration); } mSkipAnim = false; - - return movement; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 46f0690e7..8cba49b5f 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -87,7 +87,7 @@ public: void updatePtr(const MWWorld::Ptr &ptr); - Ogre::Vector3 update(float duration); + void update(float duration, Ogre::Vector3 &movement); void playGroup(const std::string &groupname, int mode, int count); void skipAnim(); From 0ce188b7cc02ef6e1cd49ceb8fd1b5e24cc1d48c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 30 Mar 2013 19:00:46 -0700 Subject: [PATCH 34/54] Store the position and rotation in MWMechanics::Movement --- apps/openmw/mwclass/npc.cpp | 9 ++------- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/movement.hpp | 11 +++++++---- apps/openmw/mwworld/player.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index a5319ada0..61d081b4b 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -368,7 +368,7 @@ namespace MWClass moveSpeed = runSpeed; else moveSpeed = walkSpeed; - if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0) + if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0) moveSpeed *= 0.75f; return moveSpeed; @@ -414,12 +414,7 @@ namespace MWClass Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const { - Ogre::Vector3 vector; - vector.x = getMovementSettings(ptr).mLeftRight; - vector.y = getMovementSettings(ptr).mForwardBackward; - vector.z = getMovementSettings(ptr).mUpDown; - - return vector; + return Ogre::Vector3(getMovementSettings(ptr).mPosition); } bool Npc::isEssential (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 5e112d54e..ea9ff7e10 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -175,12 +175,12 @@ void CharacterController::update(float duration, Ogre::Vector3 &movement) { const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Class &cls = MWWorld::Class::get(mPtr); - const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); bool onground = world->isOnGround(mPtr); bool inwater = world->isSwimming(mPtr); bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak); + const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); speed = cls.getSpeed(mPtr); /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except diff --git a/apps/openmw/mwmechanics/movement.hpp b/apps/openmw/mwmechanics/movement.hpp index 11eb83151..6c9a4b758 100644 --- a/apps/openmw/mwmechanics/movement.hpp +++ b/apps/openmw/mwmechanics/movement.hpp @@ -6,11 +6,14 @@ namespace MWMechanics /// Desired movement for an actor struct Movement { - signed char mLeftRight; // 1: wants to move left, -1: wants to move right - signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward - signed char mUpDown; + float mPosition[3]; + float mRotation[3]; - Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {} + Movement() + { + mPosition[0] = mPosition[1] = mPosition[2] = 0.0f; + mRotation[0] = mRotation[1] = mRotation[2] = 0.0f; + } }; } diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0dc8b37ef..b01b929c4 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -42,14 +42,14 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; } void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mLeftRight = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; } void Player::setForwardBackward (int value) @@ -61,14 +61,14 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; } void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; } void Player::setRunState(bool run) From 466c0086b84eaca4da61b8d3a64e9ba675ebe24a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 00:13:56 -0700 Subject: [PATCH 35/54] Use a full Movement to hand off to the world physics update --- apps/openmw/mwbase/world.hpp | 7 ++++++- apps/openmw/mwmechanics/activators.cpp | 4 +++- apps/openmw/mwmechanics/actors.cpp | 3 ++- apps/openmw/mwmechanics/actors.hpp | 1 + apps/openmw/mwmechanics/character.cpp | 17 +++++++++++------ apps/openmw/mwmechanics/character.hpp | 4 +++- apps/openmw/mwworld/worldimp.cpp | 5 +++-- 7 files changed, 29 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 67d7dda6a..8eea383eb 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -44,6 +44,11 @@ namespace MWRender class Animation; } +namespace MWMechanics +{ + class Movement; +} + namespace MWWorld { class Fallback; @@ -54,7 +59,7 @@ namespace MWWorld class ESMStore; class RefData; - typedef std::vector > PtrMovementList; + typedef std::vector > PtrMovementList; } namespace MWBase diff --git a/apps/openmw/mwmechanics/activators.cpp b/apps/openmw/mwmechanics/activators.cpp index 51fa55f4e..cbc380299 100644 --- a/apps/openmw/mwmechanics/activators.cpp +++ b/apps/openmw/mwmechanics/activators.cpp @@ -2,6 +2,8 @@ #include +#include "movement.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -57,7 +59,7 @@ void Activators::update(float duration, bool paused) { for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter) { - Ogre::Vector3 movement(0.0f); + Movement movement; iter->second.update(duration, movement); } } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a7615311b..6aae85087 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -17,6 +17,7 @@ #include "../mwbase/windowmanager.hpp" #include "creaturestats.hpp" +#include "movement.hpp" namespace MWMechanics { @@ -266,7 +267,7 @@ namespace MWMechanics for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { - Ogre::Vector3 movement(0.0f); + Movement movement; iter->second.update(duration, movement); mMovement.push_back(std::make_pair(iter->first, movement)); } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index fc4af8dd6..aabd86dc7 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -7,6 +7,7 @@ #include #include "character.hpp" +#include "movement.hpp" #include "../mwbase/world.hpp" namespace Ogre diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ea9ff7e10..3bba065ff 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -21,6 +21,8 @@ #include +#include "movement.hpp" + #include "../mwrender/animation.hpp" #include "../mwbase/environment.hpp" @@ -168,7 +170,7 @@ void CharacterController::markerEvent(float time, const std::string &evt) } -void CharacterController::update(float duration, Ogre::Vector3 &movement) +void CharacterController::update(float duration, Movement &movement) { float speed = 0.0f; if(!(getState() >= CharState_Death1)) @@ -190,14 +192,14 @@ void CharacterController::update(float duration, Ogre::Vector3 &movement) float x = cls.getJump(mPtr); if(vec.x == 0 && vec.y == 0) - movement.z += x*duration; + movement.mPosition[2] += x*duration; else { /* FIXME: this would be more correct if we were going into a jumping state, * rather than normal walking/idle states. */ //Ogre::Vector3 lat = Ogre::Vector3(vec.x, vec.y, 0.0f).normalisedCopy(); //movement += Ogre::Vector3(lat.x, lat.y, 1.0f) * x * 0.707f * duration; - movement.z += x * 0.707f * duration; + movement.mPosition[2] += x * 0.707f * duration; } //decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult; @@ -214,7 +216,7 @@ void CharacterController::update(float duration, Ogre::Vector3 &movement) : (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true); // Apply any forward/backward movement manually - movement.y += vec.y * (speed*duration); + movement.mPosition[1] += vec.y * (speed*duration); } else if(vec.y != 0.0f && speed > 0.0f) { @@ -226,7 +228,7 @@ void CharacterController::update(float duration, Ogre::Vector3 &movement) setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack) : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true); // Apply any sideways movement manually - movement.x += vec.x * (speed*duration); + movement.mPosition[0] += vec.x * (speed*duration); } else if(mAnimQueue.size() == 0) setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); @@ -235,7 +237,10 @@ void CharacterController::update(float duration, Ogre::Vector3 &movement) if(mAnimation && !mSkipAnim) { mAnimation->setSpeed(speed); - movement += mAnimation->runAnimation(duration); + Ogre::Vector3 moved = mAnimation->runAnimation(duration); + movement.mPosition[0] += moved.x; + movement.mPosition[1] += moved.y; + movement.mPosition[2] += moved.z; } mSkipAnim = false; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 8cba49b5f..61efd0be0 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -13,6 +13,8 @@ namespace MWRender namespace MWMechanics { +class Movement; + enum CharacterState { CharState_SpecialIdle, CharState_Idle, @@ -87,7 +89,7 @@ public: void updatePtr(const MWWorld::Ptr &ptr); - void update(float duration, Ogre::Vector3 &movement); + void update(float duration, Movement &movement); void playGroup(const std::string &groupname, int mode, int count); void skipAnim(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 209e4c4be..37fa73279 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -13,6 +13,7 @@ #include "../mwbase/scriptmanager.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/movement.hpp" #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" @@ -875,13 +876,13 @@ namespace MWWorld player = iter; continue; } - Ogre::Vector3 vec = mPhysics->move(iter->first, iter->second, duration, + Ogre::Vector3 vec = mPhysics->move(iter->first, Ogre::Vector3(iter->second.mPosition), duration, !isSwimming(iter->first) && !isFlying(iter->first)); moveObjectImp(iter->first, vec.x, vec.y, vec.z); } if(player != actors.end()) { - Ogre::Vector3 vec = mPhysics->move(player->first, player->second, duration, + Ogre::Vector3 vec = mPhysics->move(player->first, Ogre::Vector3(player->second.mPosition), duration, !isSwimming(player->first) && !isFlying(player->first)); moveObjectImp(player->first, vec.x, vec.y, vec.z); } From 13be61812a101d2278234044cf72a4bc5fd27440 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 10:16:02 +0200 Subject: [PATCH 36/54] Made the "Unknown class key" exception slightly more helpful --- apps/openmw/mwworld/class.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 876328641..1eb2f35bd 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -184,10 +184,13 @@ namespace MWWorld const Class& Class::get (const std::string& key) { + if (key.empty()) + throw std::logic_error ("Class::get(): attempting to get an empty key"); + std::map >::const_iterator iter = sClasses.find (key); if (iter==sClasses.end()) - throw std::logic_error ("unknown class key: " + key); + throw std::logic_error ("Class::get(): unknown class key: " + key); return *iter->second; } From 7b02ec411bcb04fb667eda5c509a9b6b33bbe806 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 01:29:24 -0700 Subject: [PATCH 37/54] Apply the rotation when updating the character controller --- apps/openmw/mwclass/npc.cpp | 7 ++++++- apps/openmw/mwclass/npc.hpp | 3 +++ apps/openmw/mwmechanics/character.cpp | 5 +++++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 3 +++ 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 61d081b4b..e3733fe7c 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -416,7 +416,12 @@ namespace MWClass { return Ogre::Vector3(getMovementSettings(ptr).mPosition); } - + + Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const + { + return Ogre::Vector3(getMovementSettings(ptr).mRotation); + } + bool Npc::isEssential (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 0f61fc8c9..1a10bce6c 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -96,6 +96,9 @@ namespace MWClass ///< Return desired movement vector (determined based on movement settings, /// stance and stats). + virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const; + ///< Return desired rotations, as euler angles. + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 3bba065ff..56de21d27 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -183,6 +183,7 @@ void CharacterController::update(float duration, Movement &movement) bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak); const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); + const Ogre::Vector3 &rot = cls.getRotationVector(mPtr); speed = cls.getSpeed(mPtr); /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except @@ -232,6 +233,10 @@ void CharacterController::update(float duration, Movement &movement) } else if(mAnimQueue.size() == 0) setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); + + movement.mRotation[0] += rot.x * duration; + movement.mRotation[1] += rot.y * duration; + movement.mRotation[2] += rot.z * duration; } if(mAnimation && !mSkipAnim) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 876328641..571815d9e 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -142,6 +142,11 @@ namespace MWWorld return Ogre::Vector3 (0, 0, 0); } + Ogre::Vector3 Class::getRotationVector (const Ptr& ptr) const + { + return Ogre::Vector3 (0, 0, 0); + } + std::pair, bool> Class::getEquipmentSlots (const Ptr& ptr) const { return std::make_pair (std::vector(), false); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 012a03bf6..36d7e97db 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -150,6 +150,9 @@ namespace MWWorld ///< Return desired movement vector (determined based on movement settings, /// stance and stats). + virtual Ogre::Vector3 getRotationVector (const Ptr& ptr) const; + ///< Return desired rotations, as euler angles. + virtual std::pair, bool> getEquipmentSlots (const Ptr& ptr) const; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? From 38d19d33d8029ecddfcc1b66f8d5a978e9b8d69e Mon Sep 17 00:00:00 2001 From: lazydev Date: Sat, 30 Mar 2013 22:18:34 +0400 Subject: [PATCH 38/54] fix for #634 --- apps/openmw/mwdialogue/filter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index cd9908d3d..f7e952956 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -198,7 +198,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c if (imData.mNumLongs) return select.selectCompare (locals.mLongs[i]); - i -= script->mData.mNumShorts; + i -= script->mData.mNumLongs; return select.selectCompare (locals.mFloats.at (i)); } From b6f2b39a2fa0139300009975818a29377b2aaf36 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 01:56:38 -0700 Subject: [PATCH 39/54] Clear the movement and rotation vector when getting them --- apps/openmw/mwclass/npc.cpp | 14 ++++++++++++-- apps/openmw/mwinput/inputmanagerimp.cpp | 6 ------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e3733fe7c..cd6b0def1 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -414,12 +414,22 @@ namespace MWClass Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const { - return Ogre::Vector3(getMovementSettings(ptr).mPosition); + MWMechanics::Movement &movement = getMovementSettings(ptr); + Ogre::Vector3 vec(movement.mPosition); + movement.mPosition[0] = 0.0f; + movement.mPosition[1] = 0.0f; + movement.mPosition[2] = 0.0f; + return vec; } Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const { - return Ogre::Vector3(getMovementSettings(ptr).mRotation); + MWMechanics::Movement &movement = getMovementSettings(ptr); + Ogre::Vector3 vec(movement.mRotation); + movement.mRotation[0] = 0.0f; + movement.mRotation[1] = 0.0f; + movement.mRotation[2] = 0.0f; + return vec; } bool Npc::isEssential (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 013c722c0..1d55ff84d 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -288,8 +288,6 @@ namespace MWInput triedToMove = true; mPlayer.setLeftRight (1); } - else - mPlayer.setLeftRight (0); if (actionIsActive(A_MoveForward)) { @@ -303,8 +301,6 @@ namespace MWInput mPlayer.setAutoMove (false); mPlayer.setForwardBackward (-1); } - else - mPlayer.setForwardBackward (0); mPlayer.setSneak(actionIsActive(A_Sneak)); @@ -313,8 +309,6 @@ namespace MWInput mPlayer.setUpDown (1); triedToMove = true; } - else - mPlayer.setUpDown (0); if (mAlwaysRunActive) mPlayer.setRunState(!actionIsActive(A_Run)); From 18e8ff7198b0b7247c3ba0fae5101ca0f653e106 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 02:24:44 -0700 Subject: [PATCH 40/54] Actually rotate the object when updating physics --- apps/openmw/mwworld/worldimp.cpp | 20 ++++++++++++++------ apps/openmw/mwworld/worldimp.hpp | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 37fa73279..ae0e02c8c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -806,13 +806,8 @@ namespace MWWorld mPhysics->scaleObject(ptr); } - void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) + void World::rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust) { - Ogre::Vector3 rot; - rot.x = Ogre::Degree(x).valueRadians(); - rot.y = Ogre::Degree(y).valueRadians(); - rot.z = Ogre::Degree(z).valueRadians(); - if (mRendering->rotateObject(ptr, rot, adjust)) { // rotate physically iff renderer confirm so @@ -827,6 +822,14 @@ namespace MWWorld } } + void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) + { + rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(), + Ogre::Degree(y).valueRadians(), + Ogre::Degree(z).valueRadians()), + adjust); + } + void World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) { copyObjectToCell(ptr,Cell,pos); @@ -876,12 +879,17 @@ namespace MWWorld player = iter; continue; } + + rotateObjectImp(iter->first, Ogre::Vector3(iter->second.mRotation), true); + Ogre::Vector3 vec = mPhysics->move(iter->first, Ogre::Vector3(iter->second.mPosition), duration, !isSwimming(iter->first) && !isFlying(iter->first)); moveObjectImp(iter->first, vec.x, vec.y, vec.z); } if(player != actors.end()) { + rotateObjectImp(player->first, Ogre::Vector3(player->second.mRotation), true); + Ogre::Vector3 vec = mPhysics->move(player->first, Ogre::Vector3(player->second.mPosition), duration, !isSwimming(player->first) && !isFlying(player->first)); moveObjectImp(player->first, vec.x, vec.y, vec.z); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 8554d904a..8cff50bd1 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -90,6 +90,8 @@ namespace MWWorld int getDaysPerMonth (int month) const; + void rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust); + bool moveObjectImp (const Ptr& ptr, float x, float y, float z); ///< @return true if the active cell (cell player is in) changed From 13c098266cbe17e49917ff3b1306765b9f853452 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 02:57:22 -0700 Subject: [PATCH 41/54] Pass player rotation through the movement settings --- apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++---- apps/openmw/mwworld/player.cpp | 16 ++++++++++++++++ apps/openmw/mwworld/player.hpp | 4 ++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1d55ff84d..c23efe579 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -538,11 +538,11 @@ namespace MWInput { resetIdleTime(); - float x = arg.state.X.rel * mCameraSensitivity * 0.2; - float y = arg.state.Y.rel * mCameraSensitivity * 0.2 * (mInvertY ? -1 : 1) * mUIYMultiplier; + float x = arg.state.X.rel * mCameraSensitivity * 0.2f; + float y = arg.state.Y.rel * mCameraSensitivity * 0.2f * (mInvertY ? -1 : 1) * mUIYMultiplier; - MWBase::World *world = MWBase::Environment::get().getWorld(); - world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true); + mPlayer.setYaw(x); + mPlayer.setPitch(-y); if (arg.state.Z.rel) MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index b01b929c4..ea8a02dee 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -84,6 +84,22 @@ namespace MWWorld MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Sneak, sneak); } + void Player::setYaw(float yaw) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[2] = yaw; + } + void Player::setPitch(float pitch) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[0] = pitch; + } + void Player::setRoll(float roll) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll; + } + MWMechanics::DrawState_ Player::getDrawState() { MWWorld::Ptr ptr = getPlayer(); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index d82d3fc32..c98551091 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -67,6 +67,10 @@ namespace MWWorld void setRunState(bool run); void setSneak(bool sneak); + + void setYaw(float yaw); + void setPitch(float pitch); + void setRoll(float roll); }; } #endif From 4836ba16f763ceca71cbc7557ebea44561d85184 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 03:50:20 -0700 Subject: [PATCH 42/54] Implement turning states --- apps/openmw/mwmechanics/character.cpp | 10 ++++++++++ apps/openmw/mwmechanics/character.hpp | 3 +++ 2 files changed, 13 insertions(+) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 56de21d27..7aff2e1d0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -75,6 +75,9 @@ static const struct { { CharState_SneakLeft, "sneakleft" }, { CharState_SneakRight, "sneakright" }, + { CharState_TurnLeft, "turnleft" }, + { CharState_TurnRight, "turnright" }, + { CharState_Jump, "jump" }, { CharState_Death1, "death1" }, @@ -231,6 +234,13 @@ void CharacterController::update(float duration, Movement &movement) // Apply any sideways movement manually movement.mPosition[0] += vec.x * (speed*duration); } + else if(rot.z != 0.0f && !inwater && !sneak) + { + if(rot.z > 0.0f) + setState(CharState_TurnRight, true); + else if(rot.z < 0.0f) + setState(CharState_TurnLeft, true); + } else if(mAnimQueue.size() == 0) setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 61efd0be0..5b5a65f79 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -54,6 +54,9 @@ enum CharacterState { CharState_SneakLeft, CharState_SneakRight, + CharState_TurnLeft, + CharState_TurnRight, + CharState_Jump, /* Death states must be last! */ From b0199c703ce0f37fbb2ea0b4a65d9cd77e7a8c38 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 13:13:46 +0200 Subject: [PATCH 43/54] Companion UI --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/dialoguemanager.hpp | 2 ++ apps/openmw/mwbase/windowmanager.hpp | 2 ++ apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 28 ++++++++++++------- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 2 ++ apps/openmw/mwgui/container.cpp | 3 ++ apps/openmw/mwgui/container.hpp | 4 +++ apps/openmw/mwgui/dialogue.cpp | 19 +++++++++++-- apps/openmw/mwgui/hud.cpp | 3 +- apps/openmw/mwgui/inventorywindow.cpp | 5 +--- apps/openmw/mwgui/inventorywindow.hpp | 4 +-- apps/openmw/mwgui/mode.hpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 14 ++++++++++ apps/openmw/mwgui/windowmanagerimp.hpp | 3 ++ apps/openmw/mwmechanics/npcstats.cpp | 22 +++++++++++++-- apps/openmw/mwmechanics/npcstats.hpp | 5 ++++ apps/openmw/mwscript/locals.cpp | 24 ++++++++++++++++ apps/openmw/mwscript/locals.hpp | 1 + apps/openmw/mwscript/scriptmanagerimp.cpp | 2 +- files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_container_window.layout | 2 +- files/mygui/openmw_inventory_window.layout | 3 +- files/mygui/openmw_text.skin.xml | 5 ++++ 23 files changed, 130 insertions(+), 27 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 41f56f993..da8d47439 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 repair soulgemdialog + merchantrepair repair soulgemdialog companionwindow ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index db86385d4..de39b212a 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -25,6 +25,8 @@ namespace MWBase virtual ~DialogueManager() {} + virtual bool isInChoice() const = 0; + virtual void startDialogue (const MWWorld::Ptr& actor) = 0; virtual void addTopic (const std::string& topic) = 0; diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 58897dc74..4d66a7742 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -201,6 +201,7 @@ namespace MWBase ///< Hides dialog and schedules dialog to be deleted. virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector()) = 0; + virtual void enterPressed () = 0; virtual int readPressedButton() = 0; ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) @@ -235,6 +236,7 @@ namespace MWBase virtual bool getPlayerSleeping() = 0; virtual void wakeUpPlayer() = 0; + virtual void showCompanionWindow(MWWorld::Ptr actor) = 0; virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startSelfEnchanting(MWWorld::Ptr soulgem) = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index b75c514a2..9380ab76c 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -117,6 +117,8 @@ namespace MWDialogue void DialogueManager::startDialogue (const MWWorld::Ptr& actor) { + mLastTopic = ""; + mChoice = -1; mIsInChoice = false; @@ -127,6 +129,9 @@ namespace MWDialogue mActorKnownTopics.clear(); + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); + win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); + //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI updateTopics(); @@ -145,8 +150,6 @@ namespace MWDialogue { //initialise the GUI MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue); - MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); - win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); creatureStats.talkedToPlayer(); @@ -160,7 +163,7 @@ namespace MWDialogue MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript); - mLastTopic = it->mId; + mLastTopic = Misc::StringUtils::lowerCase(it->mId); mLastDialogue = *info; break; } @@ -398,6 +401,11 @@ namespace MWDialogue updateTopics(); } + bool DialogueManager::isInChoice() const + { + return mIsInChoice; + } + void DialogueManager::goodbyeSelected() { // Do not close the dialogue window if the player has to answer a question @@ -424,15 +432,13 @@ namespace MWDialogue if (mDialogueMap.find(mLastTopic) != mDialogueMap.end()) { - if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic) - { - Filter filter (mActor, mChoice, mTalkedTo); + Filter filter (mActor, mChoice, mTalkedTo); + if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic + || mDialogueMap[mLastTopic].mType == ESM::Dialogue::Greeting) + { if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic], true)) { - mChoiceMap.clear(); - mChoice = -1; - mIsInChoice = false; std::string text = info->mResponse; parseText (text); @@ -440,10 +446,12 @@ namespace MWDialogue MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext)); MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId); executeScript (info->mResultScript); - mLastTopic = mLastTopic; mLastDialogue = *info; } } + mChoiceMap.clear(); + mChoice = -1; + mIsInChoice = false; } updateTopics(); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 337cf6247..a7bec31a6 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -54,6 +54,8 @@ namespace MWDialogue DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage); + virtual bool isInChoice() const; + virtual void startDialogue (const MWWorld::Ptr& actor); virtual void addTopic (const std::string& topic); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 98d818638..837766953 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -340,6 +340,9 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender) drawItems(); mDragAndDrop->mDraggedFrom->drawItems(); + mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount); + notifyItemDragged(object, mDragAndDrop->mDraggedCount); + MWBase::Environment::get().getWindowManager()->setDragDrop(false); std::string sound = MWWorld::Class::get(object).getDownSoundId(object); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 49e60aa25..03bd519f7 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -82,6 +82,10 @@ namespace MWGui void setFilter(int filter); ///< set category filter void drawItems(); + /// fired when an item was moved by drag&drop. \n + /// if it was removed from this container, count will be negative. + virtual void notifyItemDragged(MWWorld::Ptr item, int count) {} + protected: bool mDisplayEquippedItems; bool mHighlightEquippedItems; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6875b2021..b3aa27617 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -228,7 +228,8 @@ void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) void DialogueWindow::onSelectTopic(const std::string& topic, int id) { - if (!mEnabled) return; + if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice()) + return; int separatorPos = 0; for (unsigned int i=0; igetItemCount(); ++i) @@ -248,6 +249,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id) { mPersuasionDialog.setVisible(true); } + else if (topic == gmst.find("sCompanionShare")->getString()) + { + mWindowManager.pushGuiMode(GM_Companion); + mWindowManager.showCompanionWindow(mPtr); + } else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused()) { if (topic == gmst.find("sBarter")->getString()) @@ -306,7 +312,10 @@ void DialogueWindow::setKeywords(std::list keyWords) { mTopicsList->clear(); - bool anyService = mServices > 0; + bool isCompanion = !MWWorld::Class::get(mPtr).getScript(mPtr).empty() + && mPtr.getRefData().getLocals().getIntVar(MWWorld::Class::get(mPtr).getScript(mPtr), "companion"); + + bool anyService = mServices > 0 || isCompanion || mPtr.getTypeName() == typeid(ESM::NPC).name(); const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -335,9 +344,13 @@ void DialogueWindow::setKeywords(std::list keyWords) if (mServices & Service_Repair) mTopicsList->addItem(gmst.find("sRepair")->getString()); - if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name()) + if (isCompanion) + mTopicsList->addItem(gmst.find("sCompanionShare")->getString()); + + if (anyService) mTopicsList->addSeparator(); + for(std::list::iterator it = keyWords.begin(); it != keyWords.end(); ++it) { mTopicsList->addItem(*it); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 0a31a428b..84526a28d 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -234,7 +234,8 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) mDragAndDrop->mDraggedWidget = 0; MWBase::Environment::get().getWindowManager()->setDragDrop(false); - MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); + mDragAndDrop->mDraggedFrom->drawItems(); + mDragAndDrop->mDraggedFrom->notifyItemDragged(object, -mDragAndDrop->mDraggedCount); } else { diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 578ec3da3..1943ff773 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -43,7 +43,6 @@ namespace MWGui getWidget(mAvatar, "Avatar"); getWidget(mAvatarImage, "AvatarImage"); getWidget(mEncumbranceBar, "EncumbranceBar"); - getWidget(mEncumbranceText, "EncumbranceBarT"); getWidget(mFilterAll, "AllButton"); getWidget(mFilterWeapon, "WeaponButton"); getWidget(mFilterApparel, "ApparelButton"); @@ -240,9 +239,7 @@ namespace MWGui float capacity = MWWorld::Class::get(player).getCapacity(player); float encumbrance = MWWorld::Class::get(player).getEncumbrance(player); - mEncumbranceBar->setProgressRange(capacity); - mEncumbranceBar->setProgressPosition(encumbrance); - mEncumbranceText->setCaption( boost::lexical_cast(int(encumbrance)) + "/" + boost::lexical_cast(int(capacity)) ); + mEncumbranceBar->setValue(encumbrance, capacity); } void InventoryWindow::onFrame() diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 7c59bab50..95657672d 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -5,6 +5,7 @@ #include "container.hpp" #include "window_pinnable_base.hpp" +#include "widgets.hpp" namespace MWGui { @@ -36,8 +37,7 @@ namespace MWGui MyGUI::Widget* mAvatar; MyGUI::ImageBox* mAvatarImage; MyGUI::TextBox* mArmorRating; - MyGUI::ProgressBar* mEncumbranceBar; - MyGUI::TextBox* mEncumbranceText; + Widgets::MWDynamicStat* mEncumbranceBar; MyGUI::Widget* mLeftPane; MyGUI::Widget* mRightPane; diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index e9b01395f..879fcb483 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -9,6 +9,7 @@ namespace MWGui GM_Settings, // Settings window GM_Inventory, // Inventory mode GM_Container, + GM_Companion, GM_MainMenu, // Main menu mode GM_Console, // Console mode diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index eadd65787..cf14c1f51 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -58,6 +58,7 @@ #include "merchantrepair.hpp" #include "repair.hpp" #include "soulgemdialog.hpp" +#include "companionwindow.hpp" using namespace MWGui; @@ -96,6 +97,7 @@ WindowManager::WindowManager( , mMerchantRepair(NULL) , mRepair(NULL) , mSoulgemDialog(NULL) + , mCompanionWindow(NULL) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -189,6 +191,7 @@ WindowManager::WindowManager( mMerchantRepair = new MerchantRepair(*this); mRepair = new Repair(*this); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); + mCompanionWindow = new CompanionWindow(*this, mDragAndDrop, mMessageBoxManager); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -317,6 +320,7 @@ void WindowManager::updateVisible() mTrainingWindow->setVisible(false); mMerchantRepair->setVisible(false); mRepair->setVisible(false); + mCompanionWindow->setVisible(false); mHud->setVisible(mHudEnabled); @@ -417,6 +421,10 @@ void WindowManager::updateVisible() mContainerWindow->setVisible(true); mInventoryWindow->setVisible(true); break; + case GM_Companion: + mCompanionWindow->setVisible(true); + mInventoryWindow->setVisible(true); + break; case GM_Dialogue: mDialogueWindow->setVisible(true); break; @@ -676,6 +684,7 @@ void WindowManager::onFrame (float frameDuration) mSpellCreationDialog->checkReferenceAvailable(); mEnchantingDialog->checkReferenceAvailable(); mContainerWindow->checkReferenceAvailable(); + mCompanionWindow->checkReferenceAvailable(); mConsole->checkReferenceAvailable(); } @@ -1167,6 +1176,11 @@ const Translation::Storage& WindowManager::getTranslationDataStorage() const return mTranslationDataStorage; } +void WindowManager::showCompanionWindow(MWWorld::Ptr actor) +{ + mCompanionWindow->open(actor); +} + void WindowManager::changePointer(const std::string &name) { mCursor->onCursorChange(name); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 5cf7bae02..7a7adec27 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -77,6 +77,7 @@ namespace MWGui class MerchantRepair; class Repair; class SoulgemDialog; + class CompanionWindow; class WindowManager : public MWBase::WindowManager { @@ -229,6 +230,7 @@ namespace MWGui virtual bool getPlayerSleeping(); virtual void wakeUpPlayer(); + virtual void showCompanionWindow(MWWorld::Ptr actor); virtual void startSpellMaking(MWWorld::Ptr actor); virtual void startEnchanting(MWWorld::Ptr actor); virtual void startSelfEnchanting(MWWorld::Ptr soulgem); @@ -279,6 +281,7 @@ namespace MWGui MerchantRepair* mMerchantRepair; SoulgemDialog* mSoulgemDialog; Repair* mRepair; + CompanionWindow* mCompanionWindow; Translation::Storage& mTranslationDataStorage; Cursor* mCursor; diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 51e23d16e..b9aee6abf 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -21,8 +21,16 @@ #include "../mwbase/soundmanager.hpp" MWMechanics::NpcStats::NpcStats() -: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0) -, mLevelProgress(0), mDisposition(0), mVampire (0), mReputation(0), mWerewolf (false), mWerewolfKills (0) +: mMovementFlags (0) +, mDrawState (DrawState_Nothing) +, mBounty (0) +, mLevelProgress(0) +, mDisposition(0) +, mVampire (0) +, mReputation(0) +, mWerewolf (false) +, mWerewolfKills (0) +, mProfit(0) { mSkillIncreases.resize (ESM::Attribute::Length); for (int i=0; igetLocals(script); + int index = locals.getIndex(var); + char type = locals.getType(var); + if(index != -1) + { + switch(type) + { + case 's': + return mShorts.at (index); + + case 'l': + return mLongs.at (index); + + case 'f': + return mFloats.at (index); + default: + return 0; + } + } + return 0; + } bool Locals::setVarByInt(const std::string& script, const std::string& var, int val) { diff --git a/apps/openmw/mwscript/locals.hpp b/apps/openmw/mwscript/locals.hpp index e933c727f..1d9b9c3e4 100644 --- a/apps/openmw/mwscript/locals.hpp +++ b/apps/openmw/mwscript/locals.hpp @@ -17,6 +17,7 @@ namespace MWScript void configure (const ESM::Script& script); bool setVarByInt(const std::string& script, const std::string& var, int val); + int getIntVar (const std::string& script, const std::string& var); ///< if var does not exist, returns 0 }; } diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index fed5877c4..933a6e0d3 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -114,7 +114,7 @@ namespace MWScript } catch (const std::exception& e) { - std::cerr << "exeution of script " << name << " failed." << std::endl; + std::cerr << "execution of script " << name << " failed." << std::endl; if (mVerbose) std::cerr << "(" << e.what() << ")" << std::endl; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 7da28f0bf..af695ac6c 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -80,6 +80,7 @@ set(MYGUI_FILES openmw_persuasion_dialog.layout openmw_merchantrepair.layout openmw_repair.layout + openmw_companion_window.layout smallbars.png DejaVuLGCSansMono.ttf markers.png diff --git a/files/mygui/openmw_container_window.layout b/files/mygui/openmw_container_window.layout index 452196aae..69961e9be 100644 --- a/files/mygui/openmw_container_window.layout +++ b/files/mygui/openmw_container_window.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_inventory_window.layout b/files/mygui/openmw_inventory_window.layout index 41bd40f92..09842f108 100644 --- a/files/mygui/openmw_inventory_window.layout +++ b/files/mygui/openmw_inventory_window.layout @@ -6,8 +6,7 @@ - - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 71e86091c..b2a15b503 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -158,6 +158,11 @@ + + + + + From af6409b9f57880c5f8e796b62d2fd62183ddb589 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 13:50:57 +0200 Subject: [PATCH 44/54] Fix NPC physics scale problem --- libs/openengine/bullet/physic.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 8de931bbf..7b831d32c 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -89,18 +89,19 @@ namespace Physic } void PhysicActor::setScale(float scale){ - Ogre::Vector3 position = getPosition(); - Ogre::Quaternion rotation = getRotation(); //We only need to change the scaled box translation, box rotations remain the same. mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX(); mBoxScaledTranslation *= scale; if(mBody){ mEngine->dynamicsWorld->removeRigidBody(mBody); + mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody); delete mBody; + delete mRaycastingBody; } //Create the newly scaled rigid body - mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation); - mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map + mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, getPosition(), getRotation()); + mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, getPosition(), getRotation(), 0, 0, true); + mEngine->addRigidBody(mBody, false, mRaycastingBody); //Add rigid body to dynamics world, but do not add to object map } Ogre::Vector3 PhysicActor::getHalfExtents() const From bc6e1fd9816f3acb914be559e7e79b4d84edb477 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 14:36:03 +0200 Subject: [PATCH 45/54] Add missing files --- apps/openmw/mwgui/companionwindow.cpp | 107 +++++++++++++++++++++ apps/openmw/mwgui/companionwindow.hpp | 39 ++++++++ files/mygui/openmw_companion_window.layout | 26 +++++ 3 files changed, 172 insertions(+) create mode 100644 apps/openmw/mwgui/companionwindow.cpp create mode 100644 apps/openmw/mwgui/companionwindow.hpp create mode 100644 files/mygui/openmw_companion_window.layout diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp new file mode 100644 index 000000000..643cdf4c6 --- /dev/null +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -0,0 +1,107 @@ +#include "companionwindow.hpp" + +#include + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/dialoguemanager.hpp" + +#include "../mwmechanics/npcstats.hpp" + +#include "messagebox.hpp" + +namespace MWGui +{ + +CompanionWindow::CompanionWindow(MWBase::WindowManager &parWindowManager, DragAndDrop *dragAndDrop, MessageBoxManager* manager) + : ContainerBase(dragAndDrop) + , WindowBase("openmw_companion_window.layout", parWindowManager) + , mMessageBoxManager(manager) +{ + MyGUI::ScrollView* itemView; + MyGUI::Widget* containerWidget; + getWidget(containerWidget, "Items"); + getWidget(itemView, "ItemView"); + setWidgets(containerWidget, itemView); + + getWidget(mCloseButton, "CloseButton"); + getWidget(mProfitLabel, "ProfitLabel"); + getWidget(mEncumbranceBar, "EncumbranceBar"); + + mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CompanionWindow::onCloseButtonClicked); + + setCoord(200,0,600,300); +} + +void CompanionWindow::open(MWWorld::Ptr npc) +{ + openContainer(npc); + setTitle(MWWorld::Class::get(npc).getName(npc)); + drawItems(); + updateEncumbranceBar(); +} + +void CompanionWindow::notifyItemDragged(MWWorld::Ptr item, int count) +{ + if (mPtr.getTypeName() == typeid(ESM::NPC).name()) + { + MWMechanics::NpcStats& stats = MWWorld::Class::get(mPtr).getNpcStats(mPtr); + stats.modifyProfit(MWWorld::Class::get(item).getValue(item) * count); + } + updateEncumbranceBar(); +} + +void CompanionWindow::updateEncumbranceBar() +{ + float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr); + float encumbrance = MWWorld::Class::get(mPtr).getEncumbrance(mPtr); + mEncumbranceBar->setValue(encumbrance, capacity); + + if (mPtr.getTypeName() != typeid(ESM::NPC).name()) + mProfitLabel->setCaption(""); + else + { + MWMechanics::NpcStats& stats = MWWorld::Class::get(mPtr).getNpcStats(mPtr); + mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + boost::lexical_cast(stats.getProfit())); + } +} + +void CompanionWindow::onWindowResize(MyGUI::Window* window) +{ + drawItems(); +} + +void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender) +{ + if (mPtr.getTypeName() == typeid(ESM::NPC).name() && MWWorld::Class::get(mPtr).getNpcStats(mPtr).getProfit() < 0) + { + std::vector buttons; + buttons.push_back("#{sCompanionWarningButtonOne}"); + buttons.push_back("#{sCompanionWarningButtonTwo}"); + mMessageBoxManager->createInteractiveMessageBox("#{sCompanionWarningMessage}", buttons); + mMessageBoxManager->eventButtonPressed += MyGUI::newDelegate(this, &CompanionWindow::onMessageBoxButtonClicked); + } + else + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion); +} + +void CompanionWindow::onMessageBoxButtonClicked(int button) +{ + if (button == 0) + { + mPtr.getRefData().getLocals().setVarByInt(MWWorld::Class::get(mPtr).getScript(mPtr), + "minimumProfit", MWWorld::Class::get(mPtr).getNpcStats(mPtr).getProfit()); + + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion); + MWBase::Environment::get().getDialogueManager()->startDialogue (mPtr); + } +} + +void CompanionWindow::onReferenceUnavailable() +{ + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion); +} + + + +} diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp new file mode 100644 index 000000000..1b64a34d5 --- /dev/null +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -0,0 +1,39 @@ +#ifndef OPENMW_MWGUI_COMPANIONWINDOW_H +#define OPENMW_MWGUI_COMPANIONWINDOW_H + +#include "container.hpp" +#include "widgets.hpp" + +namespace MWGui +{ + class MessageBoxManager; + + class CompanionWindow : public ContainerBase, public WindowBase + { + public: + CompanionWindow(MWBase::WindowManager& parWindowManager,DragAndDrop* dragAndDrop, MessageBoxManager* manager); + virtual ~CompanionWindow() {} + + void open(MWWorld::Ptr npc); + + virtual void notifyItemDragged(MWWorld::Ptr item, int count); + + protected: + MyGUI::Button* mCloseButton; + MyGUI::TextBox* mProfitLabel; + Widgets::MWDynamicStat* mEncumbranceBar; + MessageBoxManager* mMessageBoxManager; + + void onMessageBoxButtonClicked(int button); + + void updateEncumbranceBar(); + + void onWindowResize(MyGUI::Window* window); + void onCloseButtonClicked(MyGUI::Widget* _sender); + + virtual void onReferenceUnavailable(); + }; + +} + +#endif diff --git a/files/mygui/openmw_companion_window.layout b/files/mygui/openmw_companion_window.layout new file mode 100644 index 000000000..6172dd5b1 --- /dev/null +++ b/files/mygui/openmw_companion_window.layout @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From fd0aa1a4b82c4b94bc99657c1c64272e20b95c05 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 31 Mar 2013 14:46:46 +0200 Subject: [PATCH 46/54] Issue #685: Treat : as a whitespace --- components/compiler/scanner.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 7f43c36a5..420fd8f7f 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -106,6 +106,12 @@ namespace Compiler mLoc.mLiteral.clear(); return true; } + else if (c==':') + { + // treat : as a whitespace :( + mLoc.mLiteral.clear(); + return true; + } else if (std::isdigit (c)) { bool cont = false; From 857f2b33dbdb14d5a0778929a0de7d12575ffa13 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 14:48:48 +0200 Subject: [PATCH 47/54] Fix companion layout align --- files/mygui/openmw_companion_window.layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/mygui/openmw_companion_window.layout b/files/mygui/openmw_companion_window.layout index 6172dd5b1..41a97a1ae 100644 --- a/files/mygui/openmw_companion_window.layout +++ b/files/mygui/openmw_companion_window.layout @@ -11,7 +11,7 @@ - + From 8fd961bbac29bddb7bc838c7ed29e4268ed340c7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 31 Mar 2013 15:50:48 +0200 Subject: [PATCH 48/54] Fix ReferenceInterface not resetting the Ptr after it was deleted, causing onReferenceUnavailable to be called every frame. Fix inputmanager hiding the cursor when it shouldn't. --- apps/openmw/mwgui/referenceinterface.cpp | 3 +++ apps/openmw/mwinput/inputmanagerimp.cpp | 25 +++++------------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwgui/referenceinterface.cpp b/apps/openmw/mwgui/referenceinterface.cpp index b1f7affb6..66e036d92 100644 --- a/apps/openmw/mwgui/referenceinterface.cpp +++ b/apps/openmw/mwgui/referenceinterface.cpp @@ -26,7 +26,10 @@ namespace MWGui // check if player has changed cell, or count of the reference has become 0 if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL) || mPtr.getRefData().getCount() == 0) + { + mPtr = MWWorld::Ptr(); onReferenceUnavailable(); + } mCurrentPlayerCell = playerCell; } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 33ab9b1b4..e514638bb 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -372,26 +372,11 @@ namespace MWInput void InputManager::changeInputMode(bool guiMode) { MWBase::Environment::get().getWindowManager()->setMouseVisible(guiMode); - if(guiMode) - { - // Disable mouse look - mMouseLookEnabled = false; - - mWindows.showCrosshair (false); - - // Enable GUI events - mGuiCursorEnabled = true; - } - else - { - // Enable mouse look - mMouseLookEnabled = true; - - mWindows.showCrosshair (false); - - // Disable GUI events - mGuiCursorEnabled = false; - } + mGuiCursorEnabled = guiMode; + mMouseLookEnabled = !guiMode; + if (guiMode) + mWindows.showCrosshair(false); + // if not in gui mode, the camera decides whether to show crosshair or not. } void InputManager::processChangedSettings(const Settings::CategorySettingVector& changed) From acae815cd23edd087e7e848cb92b7d51e178a571 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 31 Mar 2013 18:00:46 +0200 Subject: [PATCH 49/54] Added workaround for OpenCS compilation problems due to bug in Qt MOC compiler. For details please see: https://forum.openmw.org/viewtopic.php?f=7&t=1451 https://bugreports.qt-project.org/browse/QTBUG-22829 Signed-off-by: Lukasz Gromanowski --- apps/opencs/editor.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index c242a17ea..cbdbad36f 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -2,9 +2,9 @@ #define CS_EDITOR_H #include - +#ifndef Q_MOC_RUN #include - +#endif #include "model/doc/documentmanager.hpp" #include "view/doc/viewmanager.hpp" From 10d04c928c894d512e999b52e8cea77e8c01eea7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 15:12:10 -0700 Subject: [PATCH 50/54] Use the object's class to check if it's an actor --- .../mwmechanics/mechanicsmanagerimp.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 32fa58980..0af7a4665 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -178,10 +178,10 @@ namespace MWMechanics void MechanicsManager::add(const MWWorld::Ptr& ptr) { - if(ptr.getTypeName() == typeid(ESM::Activator).name()) - mActivators.addActivator(ptr); - else + if(MWWorld::Class::get(ptr).isActor()) mActors.addActor(ptr); + else + mActivators.addActivator(ptr); } void MechanicsManager::remove(const MWWorld::Ptr& ptr) @@ -194,10 +194,10 @@ namespace MWMechanics void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { - if(ptr.getTypeName() == typeid(ESM::Activator).name()) - mActivators.updateActivator(old, ptr); - else + if(MWWorld::Class::get(ptr).isActor()) mActors.updateActor(old, ptr); + else + mActivators.updateActivator(old, ptr); } @@ -656,17 +656,17 @@ namespace MWMechanics void MechanicsManager::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) { - if(ptr.getTypeName() == typeid(ESM::Activator).name()) - mActivators.playAnimationGroup(ptr, groupName, mode, number); - else + if(MWWorld::Class::get(ptr).isActor()) mActors.playAnimationGroup(ptr, groupName, mode, number); + else + mActivators.playAnimationGroup(ptr, groupName, mode, number); } void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr) { - if(ptr.getTypeName() == typeid(ESM::Activator).name()) - mActivators.skipAnimation(ptr); - else + if(MWWorld::Class::get(ptr).isActor()) mActors.skipAnimation(ptr); + else + mActivators.skipAnimation(ptr); } } From 04aeb3dd07f53f4cb3484287f5a73399de78ad63 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 15:29:41 -0700 Subject: [PATCH 51/54] Rename Mechanics' Activators to Objects --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwmechanics/activators.cpp | 81 ------------------- apps/openmw/mwmechanics/activators.hpp | 45 ----------- .../mwmechanics/mechanicsmanagerimp.cpp | 14 ++-- .../mwmechanics/mechanicsmanagerimp.hpp | 4 +- apps/openmw/mwmechanics/objects.cpp | 81 +++++++++++++++++++ apps/openmw/mwmechanics/objects.hpp | 45 +++++++++++ 7 files changed, 136 insertions(+), 136 deletions(-) delete mode 100644 apps/openmw/mwmechanics/activators.cpp delete mode 100644 apps/openmw/mwmechanics/activators.hpp create mode 100644 apps/openmw/mwmechanics/objects.cpp create mode 100644 apps/openmw/mwmechanics/objects.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index da8d47439..beb0b9aad 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -63,7 +63,7 @@ add_openmw_dir (mwclass ) add_openmw_dir (mwmechanics - mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators + mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow aiescort aiactivate repair enchanting ) diff --git a/apps/openmw/mwmechanics/activators.cpp b/apps/openmw/mwmechanics/activators.cpp deleted file mode 100644 index cbc380299..000000000 --- a/apps/openmw/mwmechanics/activators.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "activators.hpp" - -#include - -#include "movement.hpp" - -#include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" - -namespace MWMechanics -{ - -Activators::Activators() -{ -} - -void Activators::addActivator(const MWWorld::Ptr& ptr) -{ - MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); - if(anim != NULL) - mActivators.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true))); -} - -void Activators::removeActivator (const MWWorld::Ptr& ptr) -{ - PtrControllerMap::iterator iter = mActivators.find(ptr); - if(iter != mActivators.end()) - mActivators.erase(iter); -} - -void Activators::updateActivator(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) -{ - PtrControllerMap::iterator iter = mActivators.find(old); - if(iter != mActivators.end()) - { - CharacterController ctrl = iter->second; - mActivators.erase(iter); - - ctrl.updatePtr(ptr); - mActivators.insert(std::make_pair(ptr, ctrl)); - } -} - -void Activators::dropActivators (const MWWorld::Ptr::CellStore *cellStore) -{ - PtrControllerMap::iterator iter = mActivators.begin(); - while(iter != mActivators.end()) - { - if(iter->first.getCell()==cellStore) - mActivators.erase(iter++); - else - ++iter; - } -} - -void Activators::update(float duration, bool paused) -{ - if(!paused) - { - for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter) - { - Movement movement; - iter->second.update(duration, movement); - } - } -} - -void Activators::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) -{ - PtrControllerMap::iterator iter = mActivators.find(ptr); - if(iter != mActivators.end()) - iter->second.playGroup(groupName, mode, number); -} -void Activators::skipAnimation(const MWWorld::Ptr& ptr) -{ - PtrControllerMap::iterator iter = mActivators.find(ptr); - if(iter != mActivators.end()) - iter->second.skipAnim(); -} - -} diff --git a/apps/openmw/mwmechanics/activators.hpp b/apps/openmw/mwmechanics/activators.hpp deleted file mode 100644 index 137674a57..000000000 --- a/apps/openmw/mwmechanics/activators.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef GAME_MWMECHANICS_ACTIVATORS_H -#define GAME_MWMECHANICS_ACTOVATRS_H - -#include -#include - -#include "character.hpp" - -namespace MWWorld -{ - class Ptr; - class CellStore; -} - -namespace MWMechanics -{ - class Activators - { - typedef std::map PtrControllerMap; - PtrControllerMap mActivators; - - public: - Activators(); - - void addActivator (const MWWorld::Ptr& ptr); - ///< Register an animated activator - - void removeActivator (const MWWorld::Ptr& ptr); - ///< Deregister an activator - - void updateActivator(const MWWorld::Ptr &old, const MWWorld::Ptr& ptr); - ///< Updates an activator with a new Ptr - - void dropActivators (const MWWorld::CellStore *cellStore); - ///< Deregister all activators in the given cell. - - void update (float duration, bool paused); - ///< Update activator animations - - void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number); - void skipAnimation(const MWWorld::Ptr& ptr); - }; -} - -#endif diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 0af7a4665..c8d827921 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -181,7 +181,7 @@ namespace MWMechanics if(MWWorld::Class::get(ptr).isActor()) mActors.addActor(ptr); else - mActivators.addActivator(ptr); + mObjects.addObject(ptr); } void MechanicsManager::remove(const MWWorld::Ptr& ptr) @@ -189,7 +189,7 @@ namespace MWMechanics if(ptr == mWatched) mWatched = MWWorld::Ptr(); mActors.removeActor(ptr); - mActivators.removeActivator(ptr); + mObjects.removeObject(ptr); } void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) @@ -197,7 +197,7 @@ namespace MWMechanics if(MWWorld::Class::get(ptr).isActor()) mActors.updateActor(old, ptr); else - mActivators.updateActivator(old, ptr); + mObjects.updateObject(old, ptr); } @@ -207,7 +207,7 @@ namespace MWMechanics mWatched = MWWorld::Ptr(); mActors.dropActors(cellStore); - mActivators.dropActivators(cellStore); + mObjects.dropObjects(cellStore); } @@ -319,7 +319,7 @@ namespace MWMechanics } mActors.update(duration, paused); - mActivators.update(duration, paused); + mObjects.update(duration, paused); } void MechanicsManager::restoreDynamicStats() @@ -659,14 +659,14 @@ namespace MWMechanics if(MWWorld::Class::get(ptr).isActor()) mActors.playAnimationGroup(ptr, groupName, mode, number); else - mActivators.playAnimationGroup(ptr, groupName, mode, number); + mObjects.playAnimationGroup(ptr, groupName, mode, number); } void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr) { if(MWWorld::Class::get(ptr).isActor()) mActors.skipAnimation(ptr); else - mActivators.skipAnimation(ptr); + mObjects.skipAnimation(ptr); } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 5ad870571..4b8d42cd3 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -7,7 +7,7 @@ #include "creaturestats.hpp" #include "npcstats.hpp" -#include "activators.hpp" +#include "objects.hpp" #include "actors.hpp" namespace Ogre @@ -31,7 +31,7 @@ namespace MWMechanics bool mClassSelected; bool mRaceSelected; - Activators mActivators; + Objects mObjects; Actors mActors; void buildPlayer(); diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp new file mode 100644 index 000000000..22b996a83 --- /dev/null +++ b/apps/openmw/mwmechanics/objects.cpp @@ -0,0 +1,81 @@ +#include "objects.hpp" + +#include + +#include "movement.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +namespace MWMechanics +{ + +Objects::Objects() +{ +} + +void Objects::addObject(const MWWorld::Ptr& ptr) +{ + MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); + if(anim != NULL) + mObjects.insert(std::make_pair(ptr, CharacterController(ptr, anim, CharState_Idle, true))); +} + +void Objects::removeObject(const MWWorld::Ptr& ptr) +{ + PtrControllerMap::iterator iter = mObjects.find(ptr); + if(iter != mObjects.end()) + mObjects.erase(iter); +} + +void Objects::updateObject(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) +{ + PtrControllerMap::iterator iter = mObjects.find(old); + if(iter != mObjects.end()) + { + CharacterController ctrl = iter->second; + mObjects.erase(iter); + + ctrl.updatePtr(ptr); + mObjects.insert(std::make_pair(ptr, ctrl)); + } +} + +void Objects::dropObjects (const MWWorld::Ptr::CellStore *cellStore) +{ + PtrControllerMap::iterator iter = mObjects.begin(); + while(iter != mObjects.end()) + { + if(iter->first.getCell()==cellStore) + mObjects.erase(iter++); + else + ++iter; + } +} + +void Objects::update(float duration, bool paused) +{ + if(!paused) + { + for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter) + { + Movement movement; + iter->second.update(duration, movement); + } + } +} + +void Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number) +{ + PtrControllerMap::iterator iter = mObjects.find(ptr); + if(iter != mObjects.end()) + iter->second.playGroup(groupName, mode, number); +} +void Objects::skipAnimation(const MWWorld::Ptr& ptr) +{ + PtrControllerMap::iterator iter = mObjects.find(ptr); + if(iter != mObjects.end()) + iter->second.skipAnim(); +} + +} diff --git a/apps/openmw/mwmechanics/objects.hpp b/apps/openmw/mwmechanics/objects.hpp new file mode 100644 index 000000000..6f111985c --- /dev/null +++ b/apps/openmw/mwmechanics/objects.hpp @@ -0,0 +1,45 @@ +#ifndef GAME_MWMECHANICS_ACTIVATORS_H +#define GAME_MWMECHANICS_ACTOVATRS_H + +#include +#include + +#include "character.hpp" + +namespace MWWorld +{ + class Ptr; + class CellStore; +} + +namespace MWMechanics +{ + class Objects + { + typedef std::map PtrControllerMap; + PtrControllerMap mObjects; + + public: + Objects(); + + void addObject (const MWWorld::Ptr& ptr); + ///< Register an animated object + + void removeObject (const MWWorld::Ptr& ptr); + ///< Deregister an object + + void updateObject(const MWWorld::Ptr &old, const MWWorld::Ptr& ptr); + ///< Updates an object with a new Ptr + + void dropObjects(const MWWorld::CellStore *cellStore); + ///< Deregister all objects in the given cell. + + void update(float duration, bool paused); + ///< Update object animations + + void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number); + void skipAnimation(const MWWorld::Ptr& ptr); + }; +} + +#endif From d0703efd69ac5d7e0e8874d19005d2acdf2d9772 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 16:12:02 -0700 Subject: [PATCH 52/54] Another place to check the class' isActor method --- apps/openmw/mwmechanics/character.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 7aff2e1d0..02a5aa100 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -111,17 +111,17 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim mAnimation->setController(this); getStateInfo(mState, &mCurrentGroup); - if(ptr.getTypeName() == typeid(ESM::Activator).name()) - { - /* Don't accumulate with activators (they don't get moved). */ - mAnimation->setAccumulation(Ogre::Vector3::ZERO); - } - else + if(MWWorld::Class::get(mPtr).isActor()) { /* Accumulate along X/Y only for now, until we can figure out how we should * handle knockout and death which moves the character down. */ mAnimation->setAccumulation(Ogre::Vector3(1.0f, 1.0f, 0.0f)); } + else + { + /* Don't accumulate with non-actors. */ + mAnimation->setAccumulation(Ogre::Vector3(0.0f)); + } if(mAnimation->hasAnimation(mCurrentGroup)) mAnimation->play(mCurrentGroup, "stop", "stop", loop); } From f976eb5bd8f3a083f54adde1dab4726a923a9ad5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 31 Mar 2013 17:31:52 -0700 Subject: [PATCH 53/54] Improve mouselook scaling --- apps/openmw/mwinput/inputmanagerimp.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index e514638bb..74d581b81 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -521,11 +521,13 @@ namespace MWInput { resetIdleTime(); - float x = arg.state.X.rel * mCameraSensitivity * 0.2f; - float y = arg.state.Y.rel * mCameraSensitivity * 0.2f * (mInvertY ? -1 : 1) * mUIYMultiplier; + float x = arg.state.X.rel * (1.0f/256.0f) * mCameraSensitivity; + float y = arg.state.Y.rel * (1.0f/256.0f) * mCameraSensitivity * mCameraYMultiplier * (mInvertY ? -1 : 1); + float scale = MWBase::Environment::get().getFrameDuration(); + if(scale <= 0.0f) scale = 1.0f; - mPlayer.setYaw(x); - mPlayer.setPitch(-y); + mPlayer.setYaw(x/scale); + mPlayer.setPitch(-y/scale); if (arg.state.Z.rel) MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel); From 26db983599daee021e2608cf37eba34254f75892 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 1 Apr 2013 10:46:08 +0200 Subject: [PATCH 54/54] minor fix --- apps/openmw/mwmechanics/objects.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/objects.hpp b/apps/openmw/mwmechanics/objects.hpp index 6f111985c..3a2e51644 100644 --- a/apps/openmw/mwmechanics/objects.hpp +++ b/apps/openmw/mwmechanics/objects.hpp @@ -1,5 +1,5 @@ #ifndef GAME_MWMECHANICS_ACTIVATORS_H -#define GAME_MWMECHANICS_ACTOVATRS_H +#define GAME_MWMECHANICS_ACTOVATORS_H #include #include