From dc91211b12f7fa6b4b9c0bdd505f2618ed8125fc Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 31 Jan 2013 00:21:04 +0000 Subject: [PATCH 1/7] Fixed Small bug where scripts were being removed when they shouldn't be. Scripts should only be removed when the item is being moved to another cell, otherwise they should remain active. --- apps/openmw/mwworld/worldimp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 24d139b377..ddcace338a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -694,10 +694,11 @@ namespace MWWorld bool isPlayer = ptr == mPlayer->getPlayer(); bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; - removeContainerScripts(ptr); if (*currCell != newCell) { + removeContainerScripts(ptr); + if (isPlayer) if (!newCell.isExterior()) changeToInteriorCell(Misc::StringUtils::lowerCase(newCell.mCell->mName), pos); From 09f9557ecb516a0a4d0d3db5e0364712a0c21b8a Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 31 Jan 2013 00:34:16 +0000 Subject: [PATCH 2/7] Implemented OnPCEquip special variable --- apps/openmw/mwworld/actionequip.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 60260a812b..c519a3ee54 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -3,6 +3,9 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/scriptmanager.hpp" + +#include #include "inventorystore.hpp" #include "player.hpp" @@ -35,6 +38,8 @@ namespace MWWorld std::string npcRace = actor.get()->mBase->mRace; + bool equipped = false; + // equip the item in the first free slot for (std::vector::const_iterator slot=slots.first.begin(); slot!=slots.first.end(); ++slot) @@ -91,6 +96,7 @@ namespace MWWorld if (slot == --slots.first.end()) { invStore.equip(*slot, it); + equipped = true; break; } @@ -98,8 +104,16 @@ namespace MWWorld { // slot is not occupied invStore.equip(*slot, it); + equipped = true; break; } } + + /* Set OnPCEquip Variable on item's script, if it has a script with that variable declared */ + if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && MWWorld::Class::get(*it).getScript(*it) != ""){ + int index = MWBase::Environment::get().getScriptManager()->getLocals(MWWorld::Class::get(*it).getScript(*it)).getIndex("onpcequip"); + if(index != -1) + (*it).mRefData->getLocals().mShorts.at (index) = 1; + } } } From 0fc5ee5149534facb779c4eed37f6f8f565856c2 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 31 Jan 2013 17:46:16 +0000 Subject: [PATCH 3/7] allow OnPCEquip special variable to be of any type --- apps/openmw/mwworld/actionequip.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index c519a3ee54..2b238ead99 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -109,11 +109,28 @@ namespace MWWorld } } - /* Set OnPCEquip Variable on item's script, if it has a script with that variable declared */ - if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && MWWorld::Class::get(*it).getScript(*it) != ""){ - int index = MWBase::Environment::get().getScriptManager()->getLocals(MWWorld::Class::get(*it).getScript(*it)).getIndex("onpcequip"); + std::string script = MWWorld::Class::get(*it).getScript(*it); + + /* Set OnPCEquip Variable on item's script, if the player is equipping it, and it has a script with that variable declared */ + if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && script != "") + { + Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + int index = locals.getIndex("onpcequip"); + char type = locals.getType("onpcequip"); if(index != -1) - (*it).mRefData->getLocals().mShorts.at (index) = 1; + { + switch(type) + { + case 's': + (*it).mRefData->getLocals().mShorts.at (index) = 1; break; + + case 'l': + (*it).mRefData->getLocals().mLongs.at (index) = 1; break; + + case 'f': + (*it).mRefData->getLocals().mFloats.at (index) = 1.0; break; + } + } } } } From 9ad08520fd766e45514e479a2f8ff866be3995b6 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 31 Jan 2013 18:45:32 +0000 Subject: [PATCH 4/7] Implemented OnPCDrop special variable Scripts are responsible for resetting to 0, as investigation showed that is how vanilla handled it. --- apps/openmw/mwworld/worldimp.cpp | 44 ++++++++++++++++++++++++++++---- apps/openmw/mwworld/worldimp.hpp | 5 ++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ddcace338a..0c8027975b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2,11 +2,13 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/scriptmanager.hpp" #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" @@ -1271,6 +1273,33 @@ namespace MWWorld mRendering->toggleWater(); } + void World::PCDropped (const Ptr& item) + { + std::string script = MWWorld::Class::get(item).getScript(item); + + /* Set OnPCDrop Variable on item's script, if it has a script with that variable declared */ + if(script != "") + { + Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + int index = locals.getIndex("onpcdrop"); + char type = locals.getType("onpcdrop"); + if(index != -1) + { + switch(type) + { + case 's': + item.mRefData->getLocals().mShorts.at (index) = 1; break; + + case 'l': + item.mRefData->getLocals().mLongs.at (index) = 1; break; + + case 'f': + item.mRefData->getLocals().mFloats.at (index) = 1.0; break; + } + } + } + } + bool World::placeObject (const Ptr& object, float cursorX, float cursorY) { std::pair result = mPhysics->castRay(cursorX, cursorY); @@ -1293,9 +1322,10 @@ namespace MWWorld pos.pos[1] = -result.second[2]; pos.pos[2] = result.second[1]; - copyObjectToCell(object, *cell, pos); + Ptr dropped = copyObjectToCell(object, *cell, pos); + PCDropped(dropped); object.getRefData().setCount(0); - + return true; } @@ -1310,8 +1340,8 @@ namespace MWWorld return true; } - void - World::copyObjectToCell(const Ptr &object, CellStore &cell, const ESM::Position &pos) + + Ptr World::copyObjectToCell(const Ptr &object, CellStore &cell, const ESM::Position &pos) { /// \todo add searching correct cell for position specified MWWorld::Ptr dropped = @@ -1335,6 +1365,8 @@ namespace MWWorld } addContainerScripts(dropped, &cell); } + + return dropped; } void World::dropObjectOnGround (const Ptr& actor, const Ptr& object) @@ -1355,7 +1387,9 @@ namespace MWWorld mPhysics->castRay(orig, dir, len); pos.pos[2] = hit.second.z; - copyObjectToCell(object, *cell, pos); + Ptr dropped = copyObjectToCell(object, *cell, pos); + if(actor == mPlayer->getPlayer()) // Only call if dropped by player + PCDropped(dropped); object.getRefData().setCount(0); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index fa5b41038d..e8efb6a670 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -91,8 +91,8 @@ namespace MWWorld bool moveObjectImp (const Ptr& ptr, float x, float y, float z); ///< @return true if the active cell (cell player is in) changed - virtual void - copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); + + Ptr copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); void updateWindowManager (); void performUpdateSceneQueries (); @@ -107,6 +107,7 @@ namespace MWWorld void removeContainerScripts(const Ptr& reference); void addContainerScripts(const Ptr& reference, Ptr::CellStore* cell); + void PCDropped (const Ptr& item); public: From 0f58e03343e3d3db1da04398367a5e0704fd7a91 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 31 Jan 2013 19:04:39 +0000 Subject: [PATCH 5/7] Unequipping items will reset OnPCEquip variable --- apps/openmw/mwgui/inventorywindow.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 5390f1602e..ebbd69d80b 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -7,10 +7,13 @@ #include +#include + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/scriptmanager.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" @@ -240,6 +243,29 @@ namespace MWGui if (it != invStore.end() && *it == item) { invStore.equip(slot, invStore.end()); + std::string script = MWWorld::Class::get(*it).getScript(*it); + + /* Unset OnPCEquip Variable on item's script, if it has a script with that variable declared */ + if(script != "") + { + Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + int index = locals.getIndex("onpcequip"); + char type = locals.getType("onpcequip"); + if(index != -1) + { + switch(type) + { + case 's': + (*it).mRefData->getLocals().mShorts.at (index) = 0; break; + + case 'l': + (*it).mRefData->getLocals().mLongs.at (index) = 0; break; + + case 'f': + (*it).mRefData->getLocals().mFloats.at (index) = 0.0; break; + } + } + } return; } } From f785659297abf4b23876a875f0da5bdcb0c39ee8 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sat, 2 Feb 2013 17:36:12 +0000 Subject: [PATCH 6/7] Implemented OnPCAdd special variable Had to edit OpAddItem in miscextensions.cpp, as local variables were not being initialised for items added through it. Does not get reset on drop, as per original morrowind. --- apps/openmw/mwscript/containerextensions.cpp | 8 ++++++ apps/openmw/mwworld/containerstore.cpp | 28 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 1fa69d1fd6..4cce19b862 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -50,6 +50,14 @@ namespace MWScript MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item); ref.getPtr().getRefData().setCount (count); + + // Configure item's script variables + std::string script = MWWorld::Class::get(ref.getPtr()).getScript(ref.getPtr()); + if (script != "") + { + const ESM::Script *esmscript = MWBase::Environment::get().getWorld()->getStore().get().find (script); + ref.getPtr().getRefData().setLocals(*esmscript); + } MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr()); } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index bca4073b52..31eabb3424 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -8,9 +8,11 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwbase/scriptmanager.hpp" #include "manualref.hpp" #include "refdata.hpp" @@ -83,9 +85,31 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) CellStore *cell; Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer(); - // Items in players inventory have cell set to 0, so their scripts will never be removed + if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) - cell = 0; + { + cell = 0; // Items in players inventory have cell set to 0, so their scripts will never be removed + + // Set OnPCAdd special variable, if it is declared + Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + int index = locals.getIndex("onpcadd"); + char type = locals.getType("onpcadd"); + + if(index != -1) + { + switch(type) + { + case 's': + item.mRefData->getLocals().mShorts.at (index) = 1; break; + + case 'l': + item.mRefData->getLocals().mLongs.at (index) = 1; break; + + case 'f': + item.mRefData->getLocals().mFloats.at (index) = 1.0; break; + } + } + } else cell = player.getCell(); From ac112ef972927e96879405edca9aaf7c058440aa Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 3 Feb 2013 13:27:27 +0000 Subject: [PATCH 7/7] refactored special variable code --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 24 ++------------- apps/openmw/mwscript/locals.cpp | 41 ++++++++++++++++++++++++++ apps/openmw/mwscript/locals.hpp | 21 +++++-------- apps/openmw/mwworld/actionequip.cpp | 21 +------------ apps/openmw/mwworld/containerstore.cpp | 21 ++----------- apps/openmw/mwworld/worldimp.cpp | 22 ++------------ 7 files changed, 58 insertions(+), 94 deletions(-) create mode 100644 apps/openmw/mwscript/locals.cpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 482007090c..f61f5ead28 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -41,7 +41,7 @@ add_openmw_dir (mwscript locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions - animationextensions transformationextensions consoleextensions userextensions + animationextensions transformationextensions consoleextensions userextensions locals ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ebbd69d80b..40771af166 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -13,7 +13,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwbase/scriptmanager.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" @@ -245,27 +244,10 @@ namespace MWGui invStore.equip(slot, invStore.end()); std::string script = MWWorld::Class::get(*it).getScript(*it); - /* Unset OnPCEquip Variable on item's script, if it has a script with that variable declared */ + // Unset OnPCEquip Variable on item's script, if it has a script with that variable declared if(script != "") - { - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); - int index = locals.getIndex("onpcequip"); - char type = locals.getType("onpcequip"); - if(index != -1) - { - switch(type) - { - case 's': - (*it).mRefData->getLocals().mShorts.at (index) = 0; break; - - case 'l': - (*it).mRefData->getLocals().mLongs.at (index) = 0; break; - - case 'f': - (*it).mRefData->getLocals().mFloats.at (index) = 0.0; break; - } - } - } + (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 0); + return; } } diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp new file mode 100644 index 0000000000..53f744323e --- /dev/null +++ b/apps/openmw/mwscript/locals.cpp @@ -0,0 +1,41 @@ +#include "locals.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/scriptmanager.hpp" +#include + +namespace MWScript +{ + void Locals::configure (const ESM::Script& script) + { + mShorts.clear(); + mShorts.resize (script.mData.mNumShorts, 0); + mLongs.clear(); + mLongs.resize (script.mData.mNumLongs, 0); + mFloats.clear(); + mFloats.resize (script.mData.mNumFloats, 0); + } + + bool Locals::setVarByInt(const std::string& script, const std::string& var, int val) + { + Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); + int index = locals.getIndex(var); + char type = locals.getType(var); + if(index != -1) + { + switch(type) + { + case 's': + mShorts.at (index) = val; break; + + case 'l': + mLongs.at (index) = val; break; + + case 'f': + mFloats.at (index) = val; break; + } + return true; + } + return false; + } +} diff --git a/apps/openmw/mwscript/locals.hpp b/apps/openmw/mwscript/locals.hpp index ec02e2f126..e933c727f3 100644 --- a/apps/openmw/mwscript/locals.hpp +++ b/apps/openmw/mwscript/locals.hpp @@ -8,21 +8,16 @@ namespace MWScript { - struct Locals + class Locals { - std::vector mShorts; - std::vector mLongs; - std::vector mFloats; + public: + std::vector mShorts; + std::vector mLongs; + std::vector mFloats; + + void configure (const ESM::Script& script); + bool setVarByInt(const std::string& script, const std::string& var, int val); - void configure (const ESM::Script& script) - { - mShorts.clear(); - mShorts.resize (script.mData.mNumShorts, 0); - mLongs.clear(); - mLongs.resize (script.mData.mNumLongs, 0); - mFloats.clear(); - mFloats.resize (script.mData.mNumFloats, 0); - } }; } diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 2b238ead99..b1236f829a 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -3,7 +3,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwbase/scriptmanager.hpp" #include @@ -113,24 +112,6 @@ namespace MWWorld /* Set OnPCEquip Variable on item's script, if the player is equipping it, and it has a script with that variable declared */ if(equipped && actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() && script != "") - { - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); - int index = locals.getIndex("onpcequip"); - char type = locals.getType("onpcequip"); - if(index != -1) - { - switch(type) - { - case 's': - (*it).mRefData->getLocals().mShorts.at (index) = 1; break; - - case 'l': - (*it).mRefData->getLocals().mLongs.at (index) = 1; break; - - case 'f': - (*it).mRefData->getLocals().mFloats.at (index) = 1.0; break; - } - } - } + (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 1); } } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 31eabb3424..eb2a14d5b8 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -88,27 +88,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) { - cell = 0; // Items in players inventory have cell set to 0, so their scripts will never be removed + cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed // Set OnPCAdd special variable, if it is declared - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); - int index = locals.getIndex("onpcadd"); - char type = locals.getType("onpcadd"); - - if(index != -1) - { - switch(type) - { - case 's': - item.mRefData->getLocals().mShorts.at (index) = 1; break; - - case 'l': - item.mRefData->getLocals().mLongs.at (index) = 1; break; - - case 'f': - item.mRefData->getLocals().mFloats.at (index) = 1.0; break; - } - } + item.mRefData->getLocals().setVarByInt(script, "onpcadd", 1); } else cell = player.getCell(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0c8027975b..2926b76f8b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1277,27 +1277,9 @@ namespace MWWorld { std::string script = MWWorld::Class::get(item).getScript(item); - /* Set OnPCDrop Variable on item's script, if it has a script with that variable declared */ + // Set OnPCDrop Variable on item's script, if it has a script with that variable declared if(script != "") - { - Compiler::Locals locals = MWBase::Environment::get().getScriptManager()->getLocals(script); - int index = locals.getIndex("onpcdrop"); - char type = locals.getType("onpcdrop"); - if(index != -1) - { - switch(type) - { - case 's': - item.mRefData->getLocals().mShorts.at (index) = 1; break; - - case 'l': - item.mRefData->getLocals().mLongs.at (index) = 1; break; - - case 'f': - item.mRefData->getLocals().mFloats.at (index) = 1.0; break; - } - } - } + item.mRefData->getLocals().setVarByInt(script, "onpcdrop", 1); } bool World::placeObject (const Ptr& object, float cursorX, float cursorY)