1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-30 06:15:32 +00:00

Opening doors

This commit is contained in:
scrawl 2013-04-28 14:59:15 +02:00
parent a6b7f8e904
commit 9343b4459e
11 changed files with 137 additions and 10 deletions

View file

@ -54,7 +54,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
)
add_openmw_dir (mwclass

View file

@ -326,6 +326,9 @@ namespace MWBase
virtual void setupPlayer(bool newGame) = 0;
virtual void renderPlayer() = 0;
virtual void activateDoor(const MWWorld::Ptr& door) = 0;
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
virtual int canRest() = 0;

View file

@ -12,6 +12,7 @@
#include "../mwworld/nullaction.hpp"
#include "../mwworld/failedaction.hpp"
#include "../mwworld/actionteleport.hpp"
#include "../mwworld/actiondoor.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/inventorystore.hpp"
@ -71,7 +72,7 @@ namespace MWClass
ptr.get<ESM::Door>();
const std::string &openSound = ref->mBase->mOpenSound;
//const std::string &closeSound = ref->mBase->closeSound;
const std::string &closeSound = ref->mBase->mCloseSound;
const std::string lockedSound = "LockedDoor";
const std::string trapActivationSound = "Disarm Trap Fail";
@ -139,12 +140,11 @@ namespace MWClass
else
{
// animated door
// TODO return action for rotating the door
// This is a little pointless, but helps with testing
boost::shared_ptr<MWWorld::Action> action(new MWWorld::NullAction);
action->setSound(openSound);
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionDoor(ptr));
if (ptr.getRefData().getLocalRotation().rot[2] == 0)
action->setSound(openSound);
else
action->setSound(closeSound);
return action;
}

View file

@ -0,0 +1,16 @@
#include "actiondoor.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWWorld
{
ActionDoor::ActionDoor (const MWWorld::Ptr& object) : Action (false, object)
{
}
void ActionDoor::executeImp (const MWWorld::Ptr& actor)
{
MWBase::Environment::get().getWorld()->activateDoor(getTarget());
}
}

View file

@ -0,0 +1,18 @@
#ifndef GAME_MWWORLD_ACTIONDOOR_H
#define GAME_MWWORLD_ACTIONDOOR_H
#include "action.hpp"
#include "ptr.hpp"
namespace MWWorld
{
class ActionDoor : public Action
{
virtual void executeImp (const MWWorld::Ptr& actor);
public:
ActionDoor (const Ptr& object);
};
}
#endif

View file

@ -131,7 +131,6 @@ namespace MWWorld
return position;
}
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
bool gravity, OEngine::Physic::PhysicEngine *engine)
{
@ -390,6 +389,11 @@ namespace MWWorld
}
}
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr)
{
return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName());
}
Ogre::Vector3 PhysicsSystem::move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity)
{
return MovementSolver::move(ptr, movement, time, gravity, mEngine);

View file

@ -51,6 +51,7 @@ namespace MWWorld
bool toggleCollisionMode();
Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity);
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);

View file

@ -978,7 +978,45 @@ namespace MWWorld
!isSwimming(player->first) && !isFlying(player->first));
moveObjectImp(player->first, vec.x, vec.y, vec.z);
}
// the only purpose this has currently is to update the debug drawer
// doors
for (std::map<MWWorld::Ptr, int>::iterator it = mDoorStates.begin(); it != mDoorStates.end(); ++it)
{
if (!it->first.getRefData().getCount())
mDoorStates.erase(it);
else
{
if (mPlayer->getPlayer().getCell() != it->first.getCell())
continue;
float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees();
float diff = duration * 90 * (it->second ? 1 : -1);
float targetRot = std::min(std::max(0.f, oldRot + diff), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
std::vector<std::string> collisions = mPhysics->getCollisions(it->first);
for (std::vector<std::string>::iterator cit = collisions.begin(); cit != collisions.end(); ++cit)
{
MWWorld::Ptr ptr = getPtrViaHandle(*cit);
if (MWWorld::Class::get(ptr).isActor())
{
// figure out which side of the door the object we collided with is
Ogre::Vector3 relativePos = it->first.getRefData().getBaseNode()->
convertWorldToLocalPosition(ptr.getRefData().getBaseNode()->_getDerivedPosition());
if(relativePos.y >= 0)
targetRot = std::min(std::max(0.f, oldRot + diff*0.1f), 90.f);
else
targetRot = std::min(std::max(0.f, oldRot - diff*0.1f), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
break;
}
}
if ((targetRot == 90.f && it->second) || targetRot == 0.f)
mDoorStates.erase(it);
}
}
mPhysEngine->stepSimulation (duration);
}
@ -1480,4 +1518,20 @@ namespace MWWorld
{
mRendering->frameStarted(dt);
}
void World::activateDoor(const MWWorld::Ptr& door)
{
if (mDoorStates.find(door) != mDoorStates.end())
{
// if currently opening, then close, if closing, then open
mDoorStates[door] = !mDoorStates[door];
}
else
{
if (door.getRefData().getLocalRotation().rot[2] == 0)
mDoorStates[door] = 1; // open
else
mDoorStates[door] = 0; // close
}
}
}

View file

@ -85,6 +85,9 @@ namespace MWWorld
float mFaced2Distance;
int mNumFacing;
std::map<MWWorld::Ptr, int> mDoorStates;
///< only holds doors that are currently moving. 0 means closing, 1 opening
unsigned long lastTick;
Ogre::Timer mTimer;
@ -368,6 +371,9 @@ namespace MWWorld
virtual void setupPlayer(bool newGame);
virtual void renderPlayer();
virtual void activateDoor(const MWWorld::Ptr& door);
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest();

View file

@ -509,6 +509,29 @@ namespace Physic
}
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{
public:
std::vector<std::string> mResult;
virtual btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,
const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
{
const RigidBody* body = dynamic_cast<const RigidBody*>(colObj0Wrap->m_collisionObject);
if (body)
mResult.push_back(body->mName);
return 0.f;
}
};
std::vector<std::string> PhysicEngine::getCollisions(const std::string& name)
{
RigidBody* body = getRigidBody(name);
ContactTestResultCallback callback;
dynamicsWorld->contactTest(body, callback);
return callback.mResult;
}
void PhysicEngine::stepSimulation(double deltaT)
{
// This seems to be needed for character controller objects

View file

@ -298,6 +298,8 @@ namespace Physic
*/
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
std::vector<std::string> getCollisions(const std::string& name);
//event list of non player object
std::list<PhysicEvent> NPEventList;