This commit is contained in:
vorenon 2013-03-06 19:58:58 +01:00
commit f2f9c96963
10 changed files with 84 additions and 77 deletions

View file

@ -94,9 +94,6 @@ namespace MWGui
mPtr = actor; mPtr = actor;
clearSpells(); clearSpells();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells();
MWMechanics::Spells& merchantSpells = MWWorld::Class::get (actor).getCreatureStats (actor).getSpells(); MWMechanics::Spells& merchantSpells = MWWorld::Class::get (actor).getCreatureStats (actor).getSpells();
for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter) for (MWMechanics::Spells::TIterator iter = merchantSpells.begin(); iter!=merchantSpells.end(); ++iter)
@ -107,8 +104,8 @@ namespace MWGui
if (spell->mData.mType!=ESM::Spell::ST_Spell) if (spell->mData.mType!=ESM::Spell::ST_Spell)
continue; // don't try to sell diseases, curses or powers continue; // don't try to sell diseases, curses or powers
if (std::find (playerSpells.begin(), playerSpells.end(), *iter)!=playerSpells.end()) if (playerHasSpell(iter->first))
continue; // we have that spell already continue;
addSpell (iter->first); addSpell (iter->first);
} }
@ -118,6 +115,18 @@ namespace MWGui
mSpellsView->setCanvasSize (MyGUI::IntSize(mSpellsView->getWidth(), std::max(mSpellsView->getHeight(), mCurrentY))); mSpellsView->setCanvasSize (MyGUI::IntSize(mSpellsView->getWidth(), std::max(mSpellsView->getHeight(), mCurrentY)));
} }
bool SpellBuyingWindow::playerHasSpell(const std::string &id)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::Spells& playerSpells = MWWorld::Class::get (player).getCreatureStats (player).getSpells();
for (MWMechanics::Spells::TIterator it = playerSpells.begin(); it != playerSpells.end(); ++it)
{
if (Misc::StringUtils::ciEqual(id, it->first))
return true;
}
return false;
}
void SpellBuyingWindow::onSpellButtonClick(MyGUI::Widget* _sender) void SpellBuyingWindow::onSpellButtonClick(MyGUI::Widget* _sender)
{ {
int price = *_sender->getUserData<int>(); int price = *_sender->getUserData<int>();

View file

@ -47,6 +47,8 @@ namespace MWGui
void updateLabels(); void updateLabels();
virtual void onReferenceUnavailable(); virtual void onReferenceUnavailable();
bool playerHasSpell (const std::string& id);
}; };
} }

View file

@ -274,28 +274,31 @@ bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot
if (!isPlayer && isActive) if (!isPlayer && isActive)
{ {
Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); Ogre::Quaternion xr(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); Ogre::Quaternion yr(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); Ogre::Quaternion zr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z);
Ogre::Quaternion newo = adjust ? (xr * yr * zr) * ptr.getRefData().getBaseNode()->getOrientation() : xr * yr * zr;
rot.x = newo.x; Ogre::Quaternion xref(Ogre::Radian(-ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X);
rot.y = newo.y; Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y);
rot.z = newo.z; Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z);
Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr;
Ogre::Matrix3 mat;
newo.ToRotationMatrix(mat);
Ogre::Radian ax,ay,az;
mat.ToEulerAnglesXYZ(ax,ay,az);
rot.x = -ax.valueRadians();
rot.y = -ay.valueRadians();
rot.z = -az.valueRadians();
ptr.getRefData().getBaseNode()->setOrientation(newo); ptr.getRefData().getBaseNode()->setOrientation(newo);
} }
else if(isPlayer) else if(isPlayer)
{ {
rot.x = mPlayer->getPitch(); rot.x = -mPlayer->getPitch();
rot.z = mPlayer->getYaw(); rot.z = mPlayer->getYaw();
} }
else if (adjust)
{
// Stored and passed in radians
float *f = ptr.getRefData().getPosition().rot;
rot.x += f[0];
rot.y += f[1];
rot.z += f[2];
}
return force; return force;
} }

View file

@ -119,15 +119,15 @@ namespace MWScript
if (axis == "x") if (axis == "x")
{ {
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees());
} }
else if (axis == "y") else if (axis == "y")
{ {
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees());
} }
else if (axis == "z") else if (axis == "z")
{ {
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees());
} }
else else
throw std::runtime_error ("invalid ration axis: " + axis); throw std::runtime_error ("invalid ration axis: " + axis);
@ -148,15 +148,15 @@ namespace MWScript
if (axis=="x") if (axis=="x")
{ {
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees());
} }
else if (axis=="y") else if (axis=="y")
{ {
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees());
} }
else if (axis=="z") else if (axis=="z")
{ {
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()); runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees());
} }
else else
throw std::runtime_error ("invalid ration axis: " + axis); throw std::runtime_error ("invalid ration axis: " + axis);
@ -241,15 +241,15 @@ namespace MWScript
if(axis == "x") if(axis == "x")
{ {
runtime.push(ptr.getCellRef().mPos.pos[0]); runtime.push(ptr.getRefData().getPosition().pos[0]);
} }
else if(axis == "y") else if(axis == "y")
{ {
runtime.push(ptr.getCellRef().mPos.pos[1]); runtime.push(ptr.getRefData().getPosition().pos[1]);
} }
else if(axis == "z") else if(axis == "z")
{ {
runtime.push(ptr.getCellRef().mPos.pos[2]); runtime.push(ptr.getRefData().getPosition().pos[2]);
} }
else else
throw std::runtime_error ("invalid axis: " + axis); throw std::runtime_error ("invalid axis: " + axis);

View file

@ -100,8 +100,8 @@ namespace MWWorld
{ {
// FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why? // FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why?
return position + (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* return position + (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) *
movement; movement;
} }
@ -109,14 +109,15 @@ namespace MWWorld
bool onground = false; bool onground = false;
float remainingTime = time; float remainingTime = time;
bool isInterior = !ptr.getCell()->isExterior(); bool isInterior = !ptr.getCell()->isExterior();
Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1);
physicActor->enableCollisions(false);
Ogre::Vector3 velocity; Ogre::Vector3 velocity;
if(!gravity) if(!gravity)
{ {
velocity = (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* velocity = (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[1]), Ogre::Vector3::UNIT_Y)* Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * Ogre::Quaternion(Ogre::Radian( -refpos.rot[0]), Ogre::Vector3::UNIT_X)) *
movement / time; movement / time;
} }
else else
@ -127,9 +128,7 @@ namespace MWWorld
if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope)
onground = true; onground = true;
} }
velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time;
velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) *
movement / time;
velocity.z += physicActor->getVerticalForce(); velocity.z += physicActor->getVerticalForce();
} }
@ -191,7 +190,7 @@ namespace MWWorld
} }
physicActor->setOnGround(onground); physicActor->setOnGround(onground);
physicActor->setVerticalForce(!onground ? clippedVelocity.z - time*627.2f : 0.0f); physicActor->setVerticalForce(!onground ? clippedVelocity.z - time*627.2f : 0.0f);
physicActor->enableCollisions(true);
return newPosition; return newPosition;
} }
}; };

View file

@ -178,10 +178,11 @@ namespace MWWorld
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::vector<std::string>& master, const std::vector<std::string>& plugins, const std::vector<std::string>& master, const std::vector<std::string>& plugins,
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap, int mActivationDistanceOverride) ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride)
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride) mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride),
mFallback (fallbackMap)
{ {
mPhysics = new PhysicsSystem(renderer); mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine(); mPhysEngine = mPhysics->getEngine();
@ -247,8 +248,6 @@ namespace MWWorld
mWorldScene = new Scene(*mRendering, mPhysics); mWorldScene = new Scene(*mRendering, mPhysics);
setFallbackValues(fallbackMap);
lastTick = mTimer.getMilliseconds(); lastTick = mTimer.getMilliseconds();
} }

View file

@ -116,7 +116,7 @@ namespace MWWorld
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::vector<std::string>& master, const std::vector<std::string>& plugins, const std::vector<std::string>& master, const std::vector<std::string>& plugins,
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap, int mActivationDistanceOverride); ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride);
virtual ~World(); virtual ~World();

View file

@ -13,18 +13,9 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#define BIT(x) (1<<(x))
namespace OEngine { namespace OEngine {
namespace Physic namespace Physic
{ {
enum collisiontypes {
COL_NOTHING = 0, //<Collide with nothing
COL_WORLD = BIT(0), //<Collide with world objects
COL_ACTOR_INTERNAL = BIT(1), //<Collide internal capsule
COL_ACTOR_EXTERNAL = BIT(2), //<collide with external capsule
COL_RAYCASTING = BIT(3)
};
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
: mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) : mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0)
@ -37,6 +28,8 @@ namespace Physic
Ogre::Quaternion inverse = mBoxRotation.Inverse(); Ogre::Quaternion inverse = mBoxRotation.Inverse();
mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w); mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w);
mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map
//mBody->setCollisionFlags(COL_NOTHING);
//mBody->setMas
} }
PhysicActor::~PhysicActor() PhysicActor::~PhysicActor()
@ -50,6 +43,8 @@ namespace Physic
void PhysicActor::enableCollisions(bool collision) void PhysicActor::enableCollisions(bool collision)
{ {
if(collision && !collisionMode) mBody->translate(btVector3(0,0,-1000));
if(!collision && collisionMode) mBody->translate(btVector3(0,0,1000));
collisionMode = collision; collisionMode = collision;
} }
@ -310,7 +305,7 @@ namespace Physic
mHeightFieldMap [name] = hf; mHeightFieldMap [name] = hf;
dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal);
} }
void PhysicEngine::removeHeightField(int x, int y) void PhysicEngine::removeHeightField(int x, int y)
@ -397,11 +392,11 @@ namespace Physic
return; return;
if(body->mCollide) if(body->mCollide)
{ {
dynamicsWorld->addRigidBody(body,COL_WORLD,COL_WORLD|COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL); dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal);
} }
else else
{ {
dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD); dynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World);
} }
body->setActivationState(DISABLE_DEACTIVATION); body->setActivationState(DISABLE_DEACTIVATION);
if(addToMap){ if(addToMap){
@ -535,7 +530,7 @@ namespace Physic
float d1 = 10000.; float d1 = 10000.;
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting;
dynamicsWorld->rayTest(from, to, resultCallback1); dynamicsWorld->rayTest(from, to, resultCallback1);
if (resultCallback1.hasHit()) if (resultCallback1.hasHit())
{ {
@ -545,7 +540,7 @@ namespace Physic
} }
btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to); btCollisionWorld::ClosestRayResultCallback resultCallback2(from, to);
resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal;
dynamicsWorld->rayTest(from, to, resultCallback2); dynamicsWorld->rayTest(from, to, resultCallback2);
float d2 = 10000.; float d2 = 10000.;
if (resultCallback2.hasHit()) if (resultCallback2.hasHit())
@ -564,12 +559,12 @@ namespace Physic
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to) std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
{ {
MyRayResultCallback resultCallback1; MyRayResultCallback resultCallback1;
resultCallback1.m_collisionFilterMask = COL_WORLD|COL_RAYCASTING; resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_Raycasting;
dynamicsWorld->rayTest(from, to, resultCallback1); dynamicsWorld->rayTest(from, to, resultCallback1);
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results; std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
MyRayResultCallback resultCallback2; MyRayResultCallback resultCallback2;
resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; resultCallback2.m_collisionFilterMask = CollisionType_ActorInternal|CollisionType_ActorExternal;
dynamicsWorld->rayTest(from, to, resultCallback2); dynamicsWorld->rayTest(from, to, resultCallback2);
std::vector< std::pair<float, const btCollisionObject*> > actorResults = resultCallback2.results; std::vector< std::pair<float, const btCollisionObject*> > actorResults = resultCallback2.results;

View file

@ -43,6 +43,14 @@ namespace Physic
class PhysicEngine; class PhysicEngine;
class RigidBody; class RigidBody;
enum CollisionType {
CollisionType_Nothing = 0, //<Collide with nothing
CollisionType_World = 1<<0, //<Collide with world objects
CollisionType_ActorInternal = 1<<1, //<Collide internal capsule Still Used?
CollisionType_ActorExternal = 1<<2, //<collide with external capsule Still used?
CollisionType_Raycasting = 1<<3 //Still used?
};
/** /**
*This is just used to be able to name objects. *This is just used to be able to name objects.
*/ */
@ -129,6 +137,7 @@ namespace Physic
void operator delete (void * Data) { _aligned_free (Data); } void operator delete (void * Data) { _aligned_free (Data); }
#endif #endif
private: private:
OEngine::Physic::RigidBody* mBody; OEngine::Physic::RigidBody* mBody;

View file

@ -8,7 +8,6 @@
#include "physic.hpp" #include "physic.hpp"
enum traceWorldType enum traceWorldType
{ {
collisionWorldTrace = 1, collisionWorldTrace = 1,
@ -16,14 +15,6 @@ enum traceWorldType
bothWorldTrace = collisionWorldTrace | pickWorldTrace bothWorldTrace = collisionWorldTrace | pickWorldTrace
}; };
enum collaborativePhysicsType
{
No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass)
Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics)
Only_Pickup = 2, // This object only has pickup physics but no collision physics (example: items dropped on the ground)
Both_Physics = 3 // This object has both kinds of physics (example: activators)
};
void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass) //Traceobj was a Aedra Object void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass) //Traceobj was a Aedra Object
{ {
const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z);
@ -36,7 +27,7 @@ void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vec
const btTransform to(btrot, btend); const btTransform to(btrot, btend);
btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend); btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend);
newTraceCallback.m_collisionFilterMask = Only_Collision; newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_Raycasting;
enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback);