From 267cf4e140f95efde49afe809e19b5510aa2f0dc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Aug 2014 17:55:35 +0200 Subject: [PATCH] Implement ResetActors script instruction (Fixes #1859) --- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwscript/docs/vmformat.txt | 3 ++- .../mwscript/transformationextensions.cpp | 10 +++++++ apps/openmw/mwworld/worldimp.cpp | 27 +++++++++++++++++++ apps/openmw/mwworld/worldimp.hpp | 3 +++ components/compiler/extensions0.cpp | 2 ++ components/compiler/opcodes.hpp | 1 + 7 files changed, 48 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 02e143286f..f07bb3eb9b 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -536,6 +536,9 @@ namespace MWBase /// @see MWWorld::WeatherManager::getStormDirection virtual Ogre::Vector3 getStormDirection() const = 0; + + /// Resets all actors in the current active cells to their original location within that cell. + virtual void resetActors() = 0; }; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 7397355e35..6263325648 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -431,5 +431,6 @@ op 0x2000294-0x20002ab: SetMagicEffect op 0x20002ac-0x20002c3: SetMagicEffect, explicit op 0x20002c4-0x20002db: ModMagicEffect op 0x20002dc-0x20002f3: ModMagicEffect, explicit +op 0x20002f4: ResetActors -opcodes 0x20002f4-0x3ffffff unused +opcodes 0x20002f5-0x3ffffff unused diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 3355e705fd..42f44512a9 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -719,6 +719,15 @@ namespace MWScript } }; + class OpResetActors : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::Environment::get().getWorld()->resetActors(); + } + }; void installOpcodes (Interpreter::Interpreter& interpreter) { @@ -759,6 +768,7 @@ namespace MWScript interpreter.installSegment5(Compiler::Transformation::opcodeMoveWorldExplicit,new OpMoveWorld); interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngle, new OpGetStartingAngle); interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngleExplicit, new OpGetStartingAngle); + interpreter.installSegment5(Compiler::Transformation::opcodeResetActors, new OpResetActors); } } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f19a40313c..c1147fa035 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2989,4 +2989,31 @@ namespace MWWorld if (!interpreterContext.hasActivationBeenHandled()) interpreterContext.executeActivation(object, actor); } + + struct ResetActorsFunctor + { + bool operator() (Ptr ptr) + { + // Can't reset actors that were moved to a different cell, because we don't know what cell they came from. + // This could be fixed once we properly track actor cell changes, but may not be desirable behaviour anyhow. + if (ptr.getClass().isActor() && ptr.getCellRef().getRefNum().mContentFile != -1) + { + const ESM::Position& origPos = ptr.getCellRef().getPosition(); + MWBase::Environment::get().getWorld()->moveObject(ptr, origPos.pos[0], origPos.pos[1], origPos.pos[2]); + MWBase::Environment::get().getWorld()->rotateObject(ptr, origPos.rot[0], origPos.rot[1], origPos.rot[2]); + ptr.getClass().adjustPosition(ptr, false); + } + return true; + } + }; + void World::resetActors() + { + for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); + iter!=mWorldScene->getActiveCells().end(); ++iter) + { + CellStore* cellstore = *iter; + ResetActorsFunctor functor; + cellstore->forEach(functor); + } + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 4dade0f218..eddd056e01 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -611,6 +611,9 @@ namespace MWWorld /// @see MWWorld::WeatherManager::getStormDirection virtual Ogre::Vector3 getStormDirection() const; + + /// Resets all actors in the current active cells to their original location within that cell. + virtual void resetActors(); }; } diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index a2dc97a1a4..e12ab65eb5 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -527,6 +527,8 @@ namespace Compiler extensions.registerInstruction("move","cf",opcodeMove,opcodeMoveExplicit); extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit); extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit); + extensions.registerInstruction("resetactors","",opcodeResetActors); + extensions.registerInstruction("ra","",opcodeResetActors); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index b37a78d62d..440475773d 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -484,6 +484,7 @@ namespace Compiler const int opcodeMoveExplicit = 0x2000207; const int opcodeMoveWorld = 0x2000208; const int opcodeMoveWorldExplicit = 0x2000209; + const int opcodeResetActors = 0x20002f4; } namespace User