diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index a3b9d2cf2..abdad0fa8 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -331,6 +331,9 @@ namespace MWBase virtual void activateDoor(const MWWorld::Ptr& door) = 0; ///< activate (open or close) an non-teleport door + virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object + virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object + virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; virtual int canRest() = 0; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index d02fc9289..d1df10489 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -331,5 +331,9 @@ op 0x2000208: MoveWorld op 0x2000209: MoveWorld, explicit op 0x200020a: Fall op 0x200020b: Fall, explicit +op 0x200020c: GetStandingPC +op 0x200020d: GetStandingPC, explicit +op 0x200020e: GetStandingActor +op 0x200020f: GetStandingActor, explicit -opcodes 0x200020c-0x3ffffff unused +opcodes 0x2000210-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index a08563877..b8a400ea6 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -565,6 +565,30 @@ namespace MWScript } }; + template + class OpGetStandingPc : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push (MWBase::Environment::get().getWorld()->getPlayerStandingOn(ptr)); + } + }; + + template + class OpGetStandingActor : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push (MWBase::Environment::get().getWorld()->getActorStandingOn(ptr)); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; const int opcodeActivate = 0x2000075; @@ -608,6 +632,10 @@ namespace MWScript const int opcodeGetSquareRoot = 0x20001e7; const int opcodeFall = 0x200020a; const int opcodeFallExplicit = 0x200020b; + const int opcodeGetStandingPc = 0x200020c; + const int opcodeGetStandingPcExplicit = 0x200020d; + const int opcodeGetStandingActor = 0x200020e; + const int opcodeGetStandingActorExplicit = 0x200020f; const int opcodePlayBink = 0x20001f7; @@ -650,6 +678,8 @@ namespace MWScript extensions.registerInstruction ("setdelete", "l", opcodeSetDelete, opcodeSetDeleteExplicit); extensions.registerFunction ("getsquareroot", 'f', "f", opcodeGetSquareRoot); extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit); + extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit); + extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -698,7 +728,10 @@ namespace MWScript interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot); interpreter.installSegment5 (opcodeFall, new OpFall); interpreter.installSegment5 (opcodeFallExplicit, new OpFall); - + interpreter.installSegment5 (opcodeGetStandingPc, new OpGetStandingPc); + interpreter.installSegment5 (opcodeGetStandingPcExplicit, new OpGetStandingPc); + interpreter.installSegment5 (opcodeGetStandingActor, new OpGetStandingActor); + interpreter.installSegment5 (opcodeGetStandingActorExplicit, new OpGetStandingActor); } } } diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 327047cdc..0476870e4 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -247,15 +247,15 @@ namespace MWScript if(axis == "x") { - runtime.push(ptr.getRefData().getPosition().pos[0]); + runtime.push(ptr.getCellRef().mPos.pos[0]); } else if(axis == "y") { - runtime.push(ptr.getRefData().getPosition().pos[1]); + runtime.push(ptr.getCellRef().mPos.pos[1]); } else if(axis == "z") { - runtime.push(ptr.getRefData().getPosition().pos[2]); + runtime.push(ptr.getCellRef().mPos.pos[2]); } else throw std::runtime_error ("invalid axis: " + axis); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 086950574..7abe94aa6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -501,7 +501,7 @@ namespace MWWorld bool PhysicsSystem::toggleCollisionMode() { - for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + for(std::map::iterator it = mEngine->mActorMap.begin(); it != mEngine->mActorMap.end();it++) { if (it->first=="player") { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 9a08a1635..3fb4ff8bd 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1583,4 +1583,20 @@ namespace MWWorld return !mDoorStates[door]; // if currently opening or closing, then do the opposite return door.getRefData().getLocalRotation().rot[2] == 0; } + + bool World::getPlayerStandingOn (const MWWorld::Ptr& object) + { + MWWorld::Ptr player = mPlayer->getPlayer(); + if (!mPhysEngine->getCharacter("player")->getOnGround()) + return false; + btVector3 from (player.getRefData().getPosition().pos[0], player.getRefData().getPosition().pos[1], player.getRefData().getPosition().pos[2]); + btVector3 to = from - btVector3(0,0,5); + std::pair result = mPhysEngine->rayTest(from, to); + return result.first == object.getRefData().getBaseNode()->getName(); + } + + bool World::getActorStandingOn (const MWWorld::Ptr& object) + { + return mPhysEngine->isAnyActorStandingOn(object.getRefData().getBaseNode()->getName()); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f61f67062..a4ae3adf4 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -381,6 +381,9 @@ namespace MWWorld virtual void activateDoor(const MWWorld::Ptr& door); ///< activate (open or close) an non-teleport door + virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object + virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object + virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); virtual int canRest(); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index def69a2e8..2b59e0aad 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -267,8 +267,8 @@ namespace Physic } } - PhysicActorContainer::iterator pa_it = PhysicActorMap.begin(); - for (; pa_it != PhysicActorMap.end(); ++pa_it) + PhysicActorContainer::iterator pa_it = mActorMap.begin(); + for (; pa_it != mActorMap.end(); ++pa_it) { if (pa_it->second != NULL) { @@ -567,13 +567,13 @@ namespace Physic //dynamicsWorld->addAction( newActor->mCharacter ); - PhysicActorMap[name] = newActor; + mActorMap[name] = newActor; } void PhysicEngine::removeCharacter(const std::string &name) { - PhysicActorContainer::iterator it = PhysicActorMap.find(name); - if (it != PhysicActorMap.end() ) + PhysicActorContainer::iterator it = mActorMap.find(name); + if (it != mActorMap.end() ) { PhysicActor* act = it->second; if(act != NULL) @@ -581,16 +581,16 @@ namespace Physic delete act; } - PhysicActorMap.erase(it); + mActorMap.erase(it); } } PhysicActor* PhysicEngine::getCharacter(const std::string &name) { - PhysicActorContainer::iterator it = PhysicActorMap.find(name); - if (it != PhysicActorMap.end() ) + PhysicActorContainer::iterator it = mActorMap.find(name); + if (it != mActorMap.end() ) { - PhysicActor* act = PhysicActorMap[name]; + PhysicActor* act = mActorMap[name]; return act; } else @@ -700,4 +700,22 @@ namespace Physic max = btVector3(0,0,0); } } -}} + + bool PhysicEngine::isAnyActorStandingOn (const std::string& objectName) + { + for (PhysicActorContainer::iterator it = mActorMap.begin(); it != mActorMap.end(); ++it) + { + if (!it->second->getOnGround()) + continue; + Ogre::Vector3 pos = it->second->getPosition(); + btVector3 from (pos.x, pos.y, pos.z); + btVector3 to = from - btVector3(0,0,5); + std::pair result = rayTest(from, to); + if (result.first == objectName) + return true; + } + return false; + } + +} +} diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 8b246408a..67e94c8f8 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -288,6 +288,8 @@ namespace Physic void setSceneManager(Ogre::SceneManager* sceneMgr); + bool isAnyActorStandingOn (const std::string& objectName); + /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). */ @@ -329,7 +331,7 @@ namespace Physic RigidBodyContainer mRaycastingObjectMap; typedef std::map PhysicActorContainer; - PhysicActorContainer PhysicActorMap; + PhysicActorContainer mActorMap; Ogre::SceneManager* mSceneMgr;