diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e2cb0e5c41..e8b498de14 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 5390f1602e..40771af166 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -7,6 +7,8 @@ #include +#include + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" @@ -240,6 +242,12 @@ 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 != "") + (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 0); + return; } } 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/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 f3191e8bb2..2d257aa614 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -4,6 +4,8 @@ #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include + #include "inventorystore.hpp" #include "player.hpp" #include "class.hpp" @@ -35,6 +37,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 +95,7 @@ namespace MWWorld if (slot == --slots.first.end()) { invStore.equip(*slot, it); + equipped = true; break; } @@ -98,8 +103,15 @@ namespace MWWorld { // slot is not occupied invStore.equip(*slot, it); + equipped = true; break; } } + + 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 != "") + (*it).mRefData->getLocals().setVarByInt(script, "onpcequip", 1); } } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index bca4073b52..eb2a14d5b8 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,14 @@ 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 player's inventory have cell set to 0, so their scripts will never be removed + + // Set OnPCAdd special variable, if it is declared + 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 24d139b377..2926b76f8b 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" @@ -694,10 +696,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); @@ -1270,6 +1273,15 @@ 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 != "") + item.mRefData->getLocals().setVarByInt(script, "onpcdrop", 1); + } + bool World::placeObject (const Ptr& object, float cursorX, float cursorY) { std::pair result = mPhysics->castRay(cursorX, cursorY); @@ -1292,9 +1304,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; } @@ -1309,8 +1322,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 = @@ -1334,6 +1347,8 @@ namespace MWWorld } addContainerScripts(dropped, &cell); } + + return dropped; } void World::dropObjectOnGround (const Ptr& actor, const Ptr& object) @@ -1354,7 +1369,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: