mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 07:11:33 +00:00
Implement collision script instructions (Fixes #1111)
This commit is contained in:
parent
ccde462308
commit
543bb22e8f
13 changed files with 252 additions and 29 deletions
|
@ -404,6 +404,15 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object
|
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 bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object
|
||||||
|
virtual bool getPlayerCollidingWith(const MWWorld::Ptr& object) = 0; ///< @return true if the player is colliding with \a object
|
||||||
|
virtual bool getActorCollidingWith (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is colliding with \a object
|
||||||
|
virtual void hurtStandingActors (const MWWorld::Ptr& object, float dmgPerSecond) = 0;
|
||||||
|
///< Apply a health difference to any actors standing on \a object.
|
||||||
|
/// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed.
|
||||||
|
virtual void hurtCollidingActors (const MWWorld::Ptr& object, float dmgPerSecond) = 0;
|
||||||
|
///< Apply a health difference to any actors colliding with \a object.
|
||||||
|
/// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed.
|
||||||
|
|
||||||
virtual float getWindSpeed() = 0;
|
virtual float getWindSpeed() = 0;
|
||||||
|
|
||||||
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
|
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
|
||||||
|
|
|
@ -405,5 +405,13 @@ op 0x200024c: Face
|
||||||
op 0x200024d: Face, explicit
|
op 0x200024d: Face, explicit
|
||||||
op 0x200024e: GetStat (dummy function)
|
op 0x200024e: GetStat (dummy function)
|
||||||
op 0x200024f: GetStat (dummy function), explicit
|
op 0x200024f: GetStat (dummy function), explicit
|
||||||
|
op 0x2000250: GetCollidingPC
|
||||||
|
op 0x2000251: GetCollidingPC, explicit
|
||||||
|
op 0x2000252: GetCollidingActor
|
||||||
|
op 0x2000253: GetCollidingActor, explicit
|
||||||
|
op 0x2000254: HurtStandingActor
|
||||||
|
op 0x2000255: HurtStandingActor, explicit
|
||||||
|
op 0x2000256: HurtCollidingActor
|
||||||
|
op 0x2000257: HurtCollidingActor, explicit
|
||||||
|
|
||||||
opcodes 0x2000250-0x3ffffff unused
|
opcodes 0x2000258-0x3ffffff unused
|
||||||
|
|
|
@ -611,6 +611,60 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpGetCollidingPc : 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 R>
|
||||||
|
class OpGetCollidingActor : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
runtime.push (MWBase::Environment::get().getWorld()->getActorStandingOn(ptr));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpHurtStandingActor : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
float healthDiffPerSecond = runtime[0].mFloat;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->hurtStandingActors(ptr, healthDiffPerSecond);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class R>
|
||||||
|
class OpHurtCollidingActor : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
float healthDiffPerSecond = runtime[0].mFloat;
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->hurtCollidingActors(ptr, healthDiffPerSecond);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class OpGetWindSpeed : public Interpreter::Opcode0
|
class OpGetWindSpeed : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -967,6 +1021,14 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingPcExplicit, new OpGetStandingPc<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingPcExplicit, new OpGetStandingPc<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingActor, new OpGetStandingActor<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingActor, new OpGetStandingActor<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingActorExplicit, new OpGetStandingActor<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetStandingActorExplicit, new OpGetStandingActor<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetCollidingPc, new OpGetCollidingPc<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetCollidingPcExplicit, new OpGetCollidingPc<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetCollidingActor, new OpGetCollidingActor<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetCollidingActorExplicit, new OpGetCollidingActor<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeHurtStandingActor, new OpHurtStandingActor<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeHurtStandingActorExplicit, new OpHurtStandingActor<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeHurtCollidingActor, new OpHurtCollidingActor<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeHurtCollidingActorExplicit, new OpHurtCollidingActor<ExplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeGetWindSpeed, new OpGetWindSpeed);
|
interpreter.installSegment5 (Compiler::Misc::opcodeGetWindSpeed, new OpGetWindSpeed);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMe, new OpHitOnMe<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMe, new OpHitOnMe<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMeExplicit, new OpHitOnMe<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeHitOnMeExplicit, new OpHitOnMe<ExplicitRef>);
|
||||||
|
|
|
@ -241,7 +241,9 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
||||||
bool isFlying, float waterlevel, float slowFall, OEngine::Physic::PhysicEngine *engine)
|
bool isFlying, float waterlevel, float slowFall, OEngine::Physic::PhysicEngine *engine
|
||||||
|
, std::map<std::string, std::string>& collisionTracker
|
||||||
|
, std::map<std::string, std::string>& standingCollisionTracker)
|
||||||
{
|
{
|
||||||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||||
Ogre::Vector3 position(refpos.pos);
|
Ogre::Vector3 position(refpos.pos);
|
||||||
|
@ -318,6 +320,11 @@ namespace MWWorld
|
||||||
tracer.doTrace(colobj, position, position - Ogre::Vector3(0,0,2), engine); // check if down 2 possible
|
tracer.doTrace(colobj, position, position - Ogre::Vector3(0,0,2), engine); // check if down 2 possible
|
||||||
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
|
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
|
||||||
{
|
{
|
||||||
|
const btCollisionObject* standingOn = tracer.mHitObject;
|
||||||
|
if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn))
|
||||||
|
{
|
||||||
|
standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName;
|
||||||
|
}
|
||||||
isOnGround = true;
|
isOnGround = true;
|
||||||
// if we're on the ground, don't try to fall any more
|
// if we're on the ground, don't try to fall any more
|
||||||
velocity.z = std::max(0.0f, velocity.z);
|
velocity.z = std::max(0.0f, velocity.z);
|
||||||
|
@ -376,6 +383,14 @@ namespace MWWorld
|
||||||
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
|
remainingTime *= (1.0f-tracer.mFraction); // FIXME: remainingTime is no longer used so don't set it?
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const btCollisionObject* standingOn = tracer.mHitObject;
|
||||||
|
if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn))
|
||||||
|
{
|
||||||
|
collisionTracker[ptr.getRefData().getHandle()] = body->mName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -771,6 +786,10 @@ namespace MWWorld
|
||||||
|
|
||||||
const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt)
|
const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt)
|
||||||
{
|
{
|
||||||
|
// Collision events are only tracked for a single frame, so reset first
|
||||||
|
mCollisions.clear();
|
||||||
|
mStandingCollisions.clear();
|
||||||
|
|
||||||
mMovementResults.clear();
|
mMovementResults.clear();
|
||||||
|
|
||||||
mTimeAccum += dt;
|
mTimeAccum += dt;
|
||||||
|
@ -810,7 +829,7 @@ namespace MWWorld
|
||||||
|
|
||||||
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
||||||
world->isFlying(iter->first),
|
world->isFlying(iter->first),
|
||||||
waterlevel, slowFall, mEngine);
|
waterlevel, slowFall, mEngine, mCollisions, mStandingCollisions);
|
||||||
|
|
||||||
if (waterCollision)
|
if (waterCollision)
|
||||||
mEngine->mDynamicsWorld->removeCollisionObject(&object);
|
mEngine->mDynamicsWorld->removeCollisionObject(&object);
|
||||||
|
@ -837,4 +856,57 @@ namespace MWWorld
|
||||||
|
|
||||||
mEngine->stepSimulation(dt);
|
mEngine->stepSimulation(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem::isActorStandingOn(const Ptr &actor, const Ptr &object) const
|
||||||
|
{
|
||||||
|
const std::string& actorHandle = actor.getRefData().getHandle();
|
||||||
|
const std::string& objectHandle = object.getRefData().getHandle();
|
||||||
|
|
||||||
|
for (std::map<std::string, std::string>::const_iterator it = mStandingCollisions.begin();
|
||||||
|
it != mStandingCollisions.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == actorHandle && it->second == objectHandle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::getActorsStandingOn(const Ptr &object, std::vector<std::string> &out) const
|
||||||
|
{
|
||||||
|
const std::string& objectHandle = object.getRefData().getHandle();
|
||||||
|
|
||||||
|
for (std::map<std::string, std::string>::const_iterator it = mStandingCollisions.begin();
|
||||||
|
it != mStandingCollisions.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == objectHandle)
|
||||||
|
out.push_back(it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem::isActorCollidingWith(const Ptr &actor, const Ptr &object) const
|
||||||
|
{
|
||||||
|
const std::string& actorHandle = actor.getRefData().getHandle();
|
||||||
|
const std::string& objectHandle = object.getRefData().getHandle();
|
||||||
|
|
||||||
|
for (std::map<std::string, std::string>::const_iterator it = mCollisions.begin();
|
||||||
|
it != mCollisions.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == actorHandle && it->second == objectHandle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::getActorsCollidingWith(const Ptr &object, std::vector<std::string> &out) const
|
||||||
|
{
|
||||||
|
const std::string& objectHandle = object.getRefData().getHandle();
|
||||||
|
|
||||||
|
for (std::map<std::string, std::string>::const_iterator it = mCollisions.begin();
|
||||||
|
it != mCollisions.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == objectHandle)
|
||||||
|
out.push_back(it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,34 @@ namespace MWWorld
|
||||||
|
|
||||||
const PtrVelocityList& applyQueuedMovement(float dt);
|
const PtrVelocityList& applyQueuedMovement(float dt);
|
||||||
|
|
||||||
|
/// Return true if \a actor has been standing on \a object in this frame
|
||||||
|
/// This will trigger whenever the object is directly below the actor.
|
||||||
|
/// It doesn't matter if the actor is stationary or moving.
|
||||||
|
bool isActorStandingOn(const MWWorld::Ptr& actor, const MWWorld::Ptr& object) const;
|
||||||
|
|
||||||
|
/// Get the handle of all actors standing on \a object in this frame.
|
||||||
|
void getActorsStandingOn(const MWWorld::Ptr& object, std::vector<std::string>& out) const;
|
||||||
|
|
||||||
|
/// Return true if \a actor has collided with \a object in this frame.
|
||||||
|
/// This will detect running into objects, but will not detect climbing stairs, stepping up a small object, etc.
|
||||||
|
bool isActorCollidingWith(const MWWorld::Ptr& actor, const MWWorld::Ptr& object) const;
|
||||||
|
|
||||||
|
/// Get the handle of all actors colliding with \a object in this frame.
|
||||||
|
void getActorsCollidingWith(const MWWorld::Ptr& object, std::vector<std::string>& out) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
OEngine::Render::OgreRenderer &mRender;
|
OEngine::Render::OgreRenderer &mRender;
|
||||||
OEngine::Physic::PhysicEngine* mEngine;
|
OEngine::Physic::PhysicEngine* mEngine;
|
||||||
std::map<std::string, std::string> handleToMesh;
|
std::map<std::string, std::string> handleToMesh;
|
||||||
|
|
||||||
|
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle>
|
||||||
|
// This will detect e.g. running against a vertical wall. It will not detect climbing up stairs,
|
||||||
|
// stepping up small objects, etc.
|
||||||
|
std::map<std::string, std::string> mCollisions;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> mStandingCollisions;
|
||||||
|
|
||||||
PtrVelocityList mMovementQueue;
|
PtrVelocityList mMovementQueue;
|
||||||
PtrVelocityList mMovementResults;
|
PtrVelocityList mMovementResults;
|
||||||
|
|
||||||
|
|
|
@ -1995,18 +1995,62 @@ namespace MWWorld
|
||||||
|
|
||||||
bool World::getPlayerStandingOn (const MWWorld::Ptr& object)
|
bool World::getPlayerStandingOn (const MWWorld::Ptr& object)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = mPlayer->getPlayer();
|
MWWorld::Ptr player = getPlayerPtr();
|
||||||
if (!mPhysEngine->getCharacter("player")->getOnGround())
|
return mPhysics->isActorStandingOn(player, object);
|
||||||
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<std::string, float> result = mPhysEngine->rayTest(from, to);
|
|
||||||
return result.first == object.getRefData().getBaseNode()->getName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::getActorStandingOn (const MWWorld::Ptr& object)
|
bool World::getActorStandingOn (const MWWorld::Ptr& object)
|
||||||
{
|
{
|
||||||
return mPhysEngine->isAnyActorStandingOn(object.getRefData().getBaseNode()->getName());
|
std::vector<std::string> actors;
|
||||||
|
mPhysics->getActorsStandingOn(object, actors);
|
||||||
|
return !actors.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool World::getPlayerCollidingWith (const MWWorld::Ptr& object)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = getPlayerPtr();
|
||||||
|
return mPhysics->isActorCollidingWith(player, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool World::getActorCollidingWith (const MWWorld::Ptr& object)
|
||||||
|
{
|
||||||
|
std::vector<std::string> actors;
|
||||||
|
mPhysics->getActorsCollidingWith(object, actors);
|
||||||
|
return !actors.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::hurtStandingActors(const Ptr &object, float healthPerSecond)
|
||||||
|
{
|
||||||
|
std::vector<std::string> actors;
|
||||||
|
mPhysics->getActorsStandingOn(object, actors);
|
||||||
|
for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr actor = searchPtrViaHandle(*it); // Collision events are from the last frame, actor might no longer exist
|
||||||
|
if (actor.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
MWMechanics::DynamicStat<float> health = stats.getHealth();
|
||||||
|
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
|
||||||
|
stats.setHealth(health);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::hurtCollidingActors(const Ptr &object, float healthPerSecond)
|
||||||
|
{
|
||||||
|
std::vector<std::string> actors;
|
||||||
|
mPhysics->getActorsCollidingWith(object, actors);
|
||||||
|
for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr actor = searchPtrViaHandle(*it); // Collision events are from the last frame, actor might no longer exist
|
||||||
|
if (actor.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
MWMechanics::DynamicStat<float> health = stats.getHealth();
|
||||||
|
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
|
||||||
|
stats.setHealth(health);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float World::getWindSpeed()
|
float World::getWindSpeed()
|
||||||
|
|
|
@ -479,6 +479,15 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object
|
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 bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object
|
||||||
|
virtual bool getPlayerCollidingWith(const MWWorld::Ptr& object); ///< @return true if the player is colliding with \a object
|
||||||
|
virtual bool getActorCollidingWith (const MWWorld::Ptr& object); ///< @return true if any actor is colliding with \a object
|
||||||
|
virtual void hurtStandingActors (const MWWorld::Ptr& object, float dmgPerSecond);
|
||||||
|
///< Apply a health difference to any actors standing on \a object.
|
||||||
|
/// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed.
|
||||||
|
virtual void hurtCollidingActors (const MWWorld::Ptr& object, float dmgPerSecond);
|
||||||
|
///< Apply a health difference to any actors colliding with \a object.
|
||||||
|
/// To hurt actors, healthPerSecond should be a positive value. For a negative value, actors will be healed.
|
||||||
|
|
||||||
virtual float getWindSpeed();
|
virtual float getWindSpeed();
|
||||||
|
|
||||||
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
|
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
|
||||||
|
|
|
@ -272,6 +272,10 @@ namespace Compiler
|
||||||
extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit);
|
extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit);
|
||||||
extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit);
|
extensions.registerFunction ("getstandingpc", 'l', "", opcodeGetStandingPc, opcodeGetStandingPcExplicit);
|
||||||
extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit);
|
extensions.registerFunction ("getstandingactor", 'l', "", opcodeGetStandingActor, opcodeGetStandingActorExplicit);
|
||||||
|
extensions.registerFunction ("getcollidingpc", 'l', "", opcodeGetCollidingPc, opcodeGetCollidingPcExplicit);
|
||||||
|
extensions.registerFunction ("getcollidingactor", 'l', "", opcodeGetCollidingActor, opcodeGetCollidingActorExplicit);
|
||||||
|
extensions.registerInstruction ("hurtstandingactor", "f", opcodeHurtStandingActor, opcodeHurtStandingActorExplicit);
|
||||||
|
extensions.registerInstruction ("hurtcollidingactor", "f", opcodeHurtCollidingActor, opcodeHurtCollidingActorExplicit);
|
||||||
extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed);
|
extensions.registerFunction ("getwindspeed", 'f', "", opcodeGetWindSpeed);
|
||||||
extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit);
|
extensions.registerFunction ("hitonme", 'l', "S", opcodeHitOnMe, opcodeHitOnMeExplicit);
|
||||||
extensions.registerInstruction ("disableteleporting", "", opcodeDisableTeleporting);
|
extensions.registerInstruction ("disableteleporting", "", opcodeDisableTeleporting);
|
||||||
|
|
|
@ -238,6 +238,14 @@ namespace Compiler
|
||||||
const int opcodeGetStandingPcExplicit = 0x200020d;
|
const int opcodeGetStandingPcExplicit = 0x200020d;
|
||||||
const int opcodeGetStandingActor = 0x200020e;
|
const int opcodeGetStandingActor = 0x200020e;
|
||||||
const int opcodeGetStandingActorExplicit = 0x200020f;
|
const int opcodeGetStandingActorExplicit = 0x200020f;
|
||||||
|
const int opcodeGetCollidingPc = 0x2000250;
|
||||||
|
const int opcodeGetCollidingPcExplicit = 0x2000251;
|
||||||
|
const int opcodeGetCollidingActor = 0x2000252;
|
||||||
|
const int opcodeGetCollidingActorExplicit = 0x2000253;
|
||||||
|
const int opcodeHurtStandingActor = 0x2000254;
|
||||||
|
const int opcodeHurtStandingActorExplicit = 0x2000255;
|
||||||
|
const int opcodeHurtCollidingActor = 0x2000256;
|
||||||
|
const int opcodeHurtCollidingActorExplicit = 0x2000257;
|
||||||
const int opcodeGetWindSpeed = 0x2000212;
|
const int opcodeGetWindSpeed = 0x2000212;
|
||||||
const int opcodePlayBink = 0x20001f7;
|
const int opcodePlayBink = 0x20001f7;
|
||||||
const int opcodeGoToJail = 0x2000235;
|
const int opcodeGoToJail = 0x2000235;
|
||||||
|
|
|
@ -846,21 +846,5 @@ namespace Physic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<std::string, float> result = rayTest(from, to);
|
|
||||||
if (result.first == objectName)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,8 +296,6 @@ namespace Physic
|
||||||
|
|
||||||
void setSceneManager(Ogre::SceneManager* sceneMgr);
|
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).
|
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
|
||||||
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
|
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
|
||||||
|
|
|
@ -81,12 +81,14 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start,
|
||||||
mFraction = newTraceCallback.m_closestHitFraction;
|
mFraction = newTraceCallback.m_closestHitFraction;
|
||||||
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
||||||
mEndPos = (end-start)*mFraction + start;
|
mEndPos = (end-start)*mFraction + start;
|
||||||
|
mHitObject = newTraceCallback.m_hitCollisionObject;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mEndPos = end;
|
mEndPos = end;
|
||||||
mPlaneNormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
mPlaneNormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
||||||
mFraction = 1.0f;
|
mFraction = 1.0f;
|
||||||
|
mHitObject = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Physic
|
||||||
{
|
{
|
||||||
Ogre::Vector3 mEndPos;
|
Ogre::Vector3 mEndPos;
|
||||||
Ogre::Vector3 mPlaneNormal;
|
Ogre::Vector3 mPlaneNormal;
|
||||||
|
const btCollisionObject* mHitObject;
|
||||||
|
|
||||||
float mFraction;
|
float mFraction;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue