mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 05:53:50 +00:00
Merge remote-tracking branch 'scrawl/doors'
This commit is contained in:
commit
116ac05677
11 changed files with 159 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
16
apps/openmw/mwworld/actiondoor.cpp
Normal file
16
apps/openmw/mwworld/actiondoor.cpp
Normal 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());
|
||||
}
|
||||
}
|
18
apps/openmw/mwworld/actiondoor.hpp
Normal file
18
apps/openmw/mwworld/actiondoor.hpp
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -978,10 +978,53 @@ 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
|
||||
|
||||
processDoors(duration);
|
||||
|
||||
mPhysEngine->stepSimulation (duration);
|
||||
}
|
||||
|
||||
void World::processDoors(float duration)
|
||||
{
|
||||
std::map<MWWorld::Ptr, int>::iterator it = mDoorStates.begin();
|
||||
while (it != mDoorStates.end())
|
||||
{
|
||||
if (!mWorldScene->isCellActive(*it->first.getCell()))
|
||||
mDoorStates.erase(it++);
|
||||
else
|
||||
{
|
||||
float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees();
|
||||
float diff = duration * 90;
|
||||
float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second ? 1 : -1)), 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++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool World::toggleCollisionMode()
|
||||
{
|
||||
return mPhysics->toggleCollisionMode();;
|
||||
|
@ -1480,4 +1523,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -269,6 +272,9 @@ namespace MWWorld
|
|||
virtual void doPhysics(const PtrMovementList &actors, float duration);
|
||||
///< Run physics simulation and modify \a world accordingly.
|
||||
|
||||
virtual void processDoors(float duration);
|
||||
///< Run physics simulation and modify \a world accordingly.
|
||||
|
||||
virtual bool toggleCollisionMode();
|
||||
///< Toggle collision mode for player. If disabled player object should ignore
|
||||
/// collisions and gravity.
|
||||
|
@ -368,6 +374,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();
|
||||
|
|
|
@ -509,6 +509,43 @@ namespace Physic
|
|||
}
|
||||
}
|
||||
|
||||
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> mResult;
|
||||
|
||||
// added in bullet 2.81
|
||||
// this is just a quick hack, as there does not seem to be a BULLET_VERSION macro?
|
||||
#if defined(BT_COLLISION_OBJECT_WRAPPER_H)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* col0, int partId0, int index0,
|
||||
const btCollisionObject* col1, int partId1, int index1)
|
||||
{
|
||||
const RigidBody* body = dynamic_cast<const RigidBody*>(col0);
|
||||
if (body)
|
||||
mResult.push_back(body->mName);
|
||||
return 0.f;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue