A try to make syc_athomealchemy to work

General discussion regarding the OpenMW project.
For technical support, please use the Support subforum.
Post Reply
zelurker
Posts: 35
Joined: 05 Sep 2015, 14:46

A try to make syc_athomealchemy to work

Post by zelurker »

This is a famous mod for alchemist to be able to use alchemy apparatus without taking them from the world.
The problem comes from player->Equip(object) where object is an alchemy apparaturs, it just doesn't work with openmw.

A solution would be to call useItem from the inventorywindow :

Code: Select all

diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequi
p.cpp
index 147f229..1af3f1d 100644
--- a/apps/openmw/mwworld/actionequip.cpp
+++ b/apps/openmw/mwworld/actionequip.cpp
@@ -1,5 +1,6 @@
 #include "actionequip.hpp"
 
+#include "../mwgui/inventorywindow.hpp"
 #include "../mwbase/environment.hpp"
 #include "../mwbase/world.hpp"
 #include "../mwbase/windowmanager.hpp"
@@ -39,8 +40,10 @@ namespace MWWorld
 
         // slots that this item can be equipped in
         std::pair<std::vector<int>, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget());
-        if (slots_.first.empty())
+        if (slots_.first.empty()) {
+            MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(object);
             return;
+       }
 
         // retrieve ContainerStoreIterator to the item
         MWWorld::ContainerStoreIterator it = invStore.begin();
Seems to work. Now I am not totally sure it's safe to call useItem from there, I just hope so... !
User avatar
scrawl
Posts: 2152
Joined: 18 Feb 2012, 11:51

Re: A try to make syc_athomealchemy to work

Post by scrawl »

Seems to affect other item types as well. For example, player->equip "<potion>" makes the player drink a potion in vanilla MW.

Your patch doesn't account for Equip being called on non-player actors.

This is what I have now, but I'll do some more testing before I push it.

Code: Select all

diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp
index f8bf157..fb7eca4 100644
--- a/apps/openmw/mwbase/windowmanager.hpp
+++ b/apps/openmw/mwbase/windowmanager.hpp
@@ -148,6 +148,9 @@ namespace MWBase
             virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
             virtual MWGui::TradeWindow* getTradeWindow() = 0;
 
+            /// Make the player use an item, while updating GUI state accordingly
+            virtual void useItem(const MWWorld::Ptr& item) = 0;
+
             virtual void updateSpellWindow() = 0;
 
             virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp
index f1e474a..f2ae8dd 100644
--- a/apps/openmw/mwgui/quickkeysmenu.cpp
+++ b/apps/openmw/mwgui/quickkeysmenu.cpp
@@ -21,8 +21,6 @@
 #include "../mwmechanics/creaturestats.hpp"
 #include "../mwmechanics/actorutil.hpp"
 
-#include "../mwgui/inventorywindow.hpp"
-
 #include "itemselection.hpp"
 #include "spellview.hpp"
 #include "itemwidget.hpp"
@@ -311,7 +309,7 @@ namespace MWGui
         else if (type == Type_Item)
         {
             MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
-            MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
+            MWBase::Environment::get().getWindowManager()->useItem(item);
             MWWorld::ContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
             // change draw state only if the item is in player's right hand
             if (rightHand != store.end() && item == *rightHand)
@@ -337,7 +335,7 @@ namespace MWGui
             // equip, if it can be equipped
             if (!item.getClass().getEquipmentSlots(item).first.empty())
             {
-                MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
+                MWBase::Environment::get().getWindowManager()->useItem(item);
 
                 // make sure that item was successfully equipped
                 if (!store.isEquipped(item))
diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp
index 68a6042..8422bb3 100644
--- a/apps/openmw/mwgui/spellwindow.cpp
+++ b/apps/openmw/mwgui/spellwindow.cpp
@@ -18,7 +18,6 @@
 #include "../mwmechanics/actorutil.hpp"
 
 #include "spellicons.hpp"
-#include "inventorywindow.hpp"
 #include "confirmationdialog.hpp"
 #include "spellview.hpp"
 
@@ -104,7 +103,7 @@ namespace MWGui
         if (!alreadyEquipped
             && !item.getClass().getEquipmentSlots(item).first.empty())
         {
-            MWBase::Environment::get().getWindowManager()->getInventoryWindow()->useItem(item);
+            MWBase::Environment::get().getWindowManager()->useItem(item);
             // make sure that item was successfully equipped
             if (!store.isEquipped(item))
                 return;
diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp
index 365f2c7..90a5f74 100644
--- a/apps/openmw/mwgui/windowmanagerimp.cpp
+++ b/apps/openmw/mwgui/windowmanagerimp.cpp
@@ -1327,6 +1327,12 @@ namespace MWGui
     MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
     MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
 
+    void WindowManager::useItem(const MWWorld::Ptr &item)
+    {
+        if (mInventoryWindow)
+            mInventoryWindow->useItem(item);
+    }
+
     bool WindowManager::isAllowed (GuiWindow wnd) const
     {
         return (mAllowed & wnd) != 0;
diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp
index 336a2a1..a1f7668 100644
--- a/apps/openmw/mwgui/windowmanagerimp.hpp
+++ b/apps/openmw/mwgui/windowmanagerimp.hpp
@@ -173,6 +173,9 @@ namespace MWGui
     virtual MWGui::ConfirmationDialog* getConfirmationDialog();
     virtual MWGui::TradeWindow* getTradeWindow();
 
+    /// Make the player use an item, while updating GUI state accordingly
+    virtual void useItem(const MWWorld::Ptr& item);
+
     virtual void updateSpellWindow();
 
     virtual void setConsoleSelectedObject(const MWWorld::Ptr& object);
diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp
index 20ca2b5..ec14add 100644
--- a/apps/openmw/mwscript/containerextensions.cpp
+++ b/apps/openmw/mwscript/containerextensions.cpp
@@ -191,11 +191,13 @@ namespace MWScript
                     if (it == invStore.end())
                         throw std::runtime_error("Item to equip not found");
 
-                    MWWorld::ActionEquip action (*it);
-                    action.execute(ptr);
-
-                    if (ptr == MWMechanics::getPlayer() && !ptr.getClass().getScript(ptr).empty())
-                        ptr.getRefData().getLocals().setVarByInt(ptr.getClass().getScript(ptr), "onpcequip", 1);
+                    if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
+                        MWBase::Environment::get().getWindowManager()->useItem(*it);
+                    else
+                    {
+                        boost::shared_ptr<MWWorld::Action> action = it->getClass().use(*it);
+                        action->execute(ptr);
+                    }
                 }
         };
 
zelurker
Posts: 35
Joined: 05 Sep 2015, 14:46

Re: A try to make syc_athomealchemy to work

Post by zelurker »

Ok, thanks, I'll wait for the push then !
dteviot
Posts: 144
Joined: 17 Dec 2014, 20:29

Re: A try to make syc_athomealchemy to work

Post by dteviot »

scrawl wrote: + if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
You might like to use:
if (ptr == MWMechanics::getPlayer())
Post Reply