Merge remote-tracking branch 'scrawl/master'

openmw-35
Marc Zinnschlag 10 years ago
commit 640d473866

@ -15,7 +15,7 @@
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp> #include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/ogreinit/ogreinit.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include <components/bsa/resources.hpp> #include <components/bsa/resources.hpp>
#include "model/doc/document.hpp" #include "model/doc/document.hpp"
@ -35,6 +35,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
NifOgre::Loader::setShowMarkers(true);
mOverlaySystem.reset (new CSVRender::OverlaySystem); mOverlaySystem.reset (new CSVRender::OverlaySystem);
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true, Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,

@ -16,7 +16,7 @@ namespace CSVWorld
PhysicsSystem::PhysicsSystem() PhysicsSystem::PhysicsSystem()
{ {
// Create physics. shapeLoader is deleted by the physic engine // Create physics. shapeLoader is deleted by the physic engine
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(true);
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader); mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
} }

@ -42,6 +42,12 @@
namespace namespace
{ {
bool isConscious(const MWWorld::Ptr& ptr)
{
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
return !stats.isDead() && !stats.getKnockedDown();
}
void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& actor) void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& actor)
{ {
if (bound) if (bound)
@ -1101,12 +1107,12 @@ namespace MWMechanics
updateCrimePersuit(iter->first, duration); updateCrimePersuit(iter->first, duration);
if (iter->first != player) if (iter->first != player)
iter->first.getClass().getCreatureStats(iter->first).getAiSequence().execute(iter->first,iter->second->getAiState(), duration);
CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
if(!stats.isDead())
{ {
if (stats.getAiSequence().isInCombat()) hostilesCount++; CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
if (isConscious(iter->first))
stats.getAiSequence().execute(iter->first,iter->second->getAiState(), duration);
if (stats.getAiSequence().isInCombat() && !stats.isDead()) hostilesCount++;
} }
} }
@ -1515,7 +1521,9 @@ namespace MWMechanics
for (PtrActorMap::iterator it = map.begin(); it != map.end(); ++it) for (PtrActorMap::iterator it = map.begin(); it != map.end(); ++it)
{ {
MWWorld::Ptr ptr = it->first; MWWorld::Ptr ptr = it->first;
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()
|| !isConscious(ptr)
|| ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
continue; continue;
MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence();
seq.fastForward(ptr, it->second->getAiState()); seq.fastForward(ptr, it->second->getAiState());

@ -152,8 +152,7 @@ bool AiSequence::isPackageDone() const
void AiSequence::execute (const MWWorld::Ptr& actor, AiState& state,float duration) void AiSequence::execute (const MWWorld::Ptr& actor, AiState& state,float duration)
{ {
if(actor != MWBase::Environment::get().getWorld()->getPlayerPtr() if(actor != MWBase::Environment::get().getWorld()->getPlayerPtr())
&& !actor.getClass().getCreatureStats(actor).getKnockedDown())
{ {
if (!mPackages.empty()) if (!mPackages.empty())
{ {

@ -308,22 +308,26 @@ namespace MWMechanics
// Play idle voiced dialogue entries randomly // Play idle voiced dialogue entries randomly
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified(); int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
if (hello > 0 && !MWBase::Environment::get().getWorld()->isSwimming(actor) if (hello > 0 && !MWBase::Environment::get().getWorld()->isSwimming(actor)
&& actor.getRefData().getPosition().pos[2] < 3000 && && MWBase::Environment::get().getSoundManager()->sayDone(actor))
MWBase::Environment::get().getSoundManager()->sayDone(actor))
{ {
float roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 10000; // [0, 9999]
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
// Don't bother if the player is out of hearing range
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore() static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat(); .get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
float x = fVoiceIdleOdds * MWBase::Environment::get().getFrameDuration(); float roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 10000;
// In vanilla MW the chance was FPS dependent, and did not allow proper changing of fVoiceIdleOdds
// due to the roll being an integer.
// Our implementation does not have these issues, so needs to be recalibrated. We chose to
// use the chance MW would have when run at 60 FPS with the default value of the GMST for calibration.
float x = fVoiceIdleOdds * 0.6 * (MWBase::Environment::get().getFrameDuration() / 0.1);
// Only say Idle voices when player is in LOS // Only say Idle voices when player is in LOS
// A bit counterintuitive, likely vanilla did this to reduce the appearance of // A bit counterintuitive, likely vanilla did this to reduce the appearance of
// voices going through walls? // voices going through walls?
if (roll < x && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500 if (roll < x && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos))
< 3000*3000 // maybe should be fAudioVoiceDefaultMaxDistance*fAudioMaxDistanceMult instead
&& MWBase::Environment::get().getWorld()->getLOS(player, actor)) && MWBase::Environment::get().getWorld()->getLOS(player, actor))
MWBase::Environment::get().getDialogueManager()->say(actor, "idle"); MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
} }

@ -70,13 +70,15 @@ void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Phys
if (bone == NULL) if (bone == NULL)
continue; continue;
btCompoundShape* compound = dynamic_cast<btCompoundShape*>(instance.mCompound); btCompoundShape* compound = static_cast<btCompoundShape*>(instance.mCompound);
btTransform trans; btTransform trans;
trans.setOrigin(BtOgre::Convert::toBullet(bone->_getDerivedPosition())); trans.setOrigin(BtOgre::Convert::toBullet(bone->_getDerivedPosition()) * compound->getLocalScaling());
trans.setRotation(BtOgre::Convert::toBullet(bone->_getDerivedOrientation())); trans.setRotation(BtOgre::Convert::toBullet(bone->_getDerivedOrientation()));
compound->getChildShape(shapeIt->second)->setLocalScaling(BtOgre::Convert::toBullet(bone->_getDerivedScale())); compound->getChildShape(shapeIt->second)->setLocalScaling(
compound->getLocalScaling() *
BtOgre::Convert::toBullet(bone->_getDerivedScale()));
compound->updateChildTransform(shapeIt->second, trans); compound->updateChildTransform(shapeIt->second, trans);
} }
@ -348,6 +350,8 @@ namespace MWWorld
velocity *= 1.f-(fStromWalkMult * (angle.valueDegrees()/180.f)); velocity *= 1.f-(fStromWalkMult * (angle.valueDegrees()/180.f));
} }
Ogre::Vector3 origVelocity = velocity;
Ogre::Vector3 newPosition = position; Ogre::Vector3 newPosition = position;
/* /*
* A loop to find newPosition using tracer, if successful different from the starting position. * A loop to find newPosition using tracer, if successful different from the starting position.
@ -425,10 +429,18 @@ namespace MWWorld
else else
{ {
// Can't move this way, try to find another spot along the plane // Can't move this way, try to find another spot along the plane
Ogre::Real movelen = velocity.normalise(); Ogre::Vector3 direction = velocity;
Ogre::Real movelen = direction.normalise();
Ogre::Vector3 reflectdir = velocity.reflect(tracer.mPlaneNormal); Ogre::Vector3 reflectdir = velocity.reflect(tracer.mPlaneNormal);
reflectdir.normalise(); reflectdir.normalise();
velocity = slide(reflectdir, tracer.mPlaneNormal)*movelen;
Ogre::Vector3 newVelocity = slide(reflectdir, tracer.mPlaneNormal)*movelen;
if ((newVelocity-velocity).squaredLength() < 0.01)
break;
if (velocity.dotProduct(origVelocity) <= 0.f)
break;
velocity = newVelocity;
// Do not allow sliding upward if there is gravity. Stepping will have taken // Do not allow sliding upward if there is gravity. Stepping will have taken
// care of that. // care of that.

@ -21,6 +21,18 @@
namespace namespace
{ {
void addObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
MWRender::RenderingManager& rendering)
{
std::string model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr));
std::string id = ptr.getClass().getId(ptr);
if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker")
model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
rendering.addObject(ptr, model);
ptr.getClass().insertObject (ptr, model, physics);
}
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
MWRender::RenderingManager& rendering) MWRender::RenderingManager& rendering)
{ {
@ -80,10 +92,7 @@ namespace
{ {
try try
{ {
const std::string& model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr)); addObject(ptr, mPhysics, mRendering);
mRendering.addObject(ptr, model);
ptr.getClass().insertObject (ptr, model, mPhysics);
updateObjectLocalRotation(ptr, mPhysics, mRendering); updateObjectLocalRotation(ptr, mPhysics, mRendering);
if (ptr.getRefData().getBaseNode()) if (ptr.getRefData().getBaseNode())
{ {
@ -530,9 +539,7 @@ namespace MWWorld
void Scene::addObjectToScene (const Ptr& ptr) void Scene::addObjectToScene (const Ptr& ptr)
{ {
const std::string& model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr)); addObject(ptr, *mPhysics, mRendering);
mRendering.addObject(ptr, model);
ptr.getClass().insertObject (ptr, model, *mPhysics);
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true); MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale()); MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
} }

@ -2107,6 +2107,9 @@ namespace MWWorld
Ogre::Vector3 playerPos(refdata.getPosition().pos); Ogre::Vector3 playerPos(refdata.getPosition().pos);
const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle()); const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
if (!physactor)
throw std::runtime_error("can't find player");
if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos) || isWalkingOnWater(player)) if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos) || isWalkingOnWater(player))
return 2; return 2;
if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) || if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) ||
@ -2326,9 +2329,15 @@ namespace MWWorld
if (!targetActor.getRefData().getBaseNode() || !targetActor.getRefData().getBaseNode()) if (!targetActor.getRefData().getBaseNode() || !targetActor.getRefData().getBaseNode())
return false; // not in active cell return false; // not in active cell
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(actor.getRefData().getHandle())->getHalfExtents(); OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle());
OEngine::Physic::PhysicActor* actor2 = mPhysEngine->getCharacter(targetActor.getRefData().getHandle());
if (!actor1 || !actor2)
return false;
Ogre::Vector3 halfExt1 = actor1->getHalfExtents();
const float* pos1 = actor.getRefData().getPosition().pos; const float* pos1 = actor.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetActor.getRefData().getHandle())->getHalfExtents(); Ogre::Vector3 halfExt2 = actor2->getHalfExtents();
const float* pos2 = targetActor.getRefData().getPosition().pos; const float* pos2 = targetActor.getRefData().getPosition().pos;
btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z*2*0.9); // eye level btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z*2*0.9); // eye level

@ -158,7 +158,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
mShape->mAutogenerated = hasAutoGeneratedCollision(node); mShape->mAutogenerated = hasAutoGeneratedCollision(node);
//do a first pass //do a first pass
handleNode(node,0,false,false,false); handleNode(node,0,false,false);
if(mBoundingBox != NULL) if(mBoundingBox != NULL)
{ {
@ -232,7 +232,7 @@ bool ManualBulletShapeLoader::hasAutoGeneratedCollision(Nif::Node const * rootNo
void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
bool isCollisionNode, bool isCollisionNode,
bool raycasting, bool isMarker, bool isAnimated) bool raycasting, bool isAnimated)
{ {
// Accumulate the flags from all the child nodes. This works for all // Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least. // the flags we currently use, at least.
@ -254,13 +254,6 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
if(node->recType == Nif::RC_AvoidNode) if(node->recType == Nif::RC_AvoidNode)
flags |= 0x800; flags |= 0x800;
// Marker objects
/// \todo don't do this in the editor
std::string nodename = node->name;
Misc::StringUtils::toLower(nodename);
if (nodename.find("marker") != std::string::npos)
isMarker = true;
// Check for extra data // Check for extra data
Nif::Extra const *e = node; Nif::Extra const *e = node;
while (!e->extra.empty()) while (!e->extra.empty())
@ -281,16 +274,14 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
// No collision. Use an internal flag setting to mark this. // No collision. Use an internal flag setting to mark this.
flags |= 0x800; flags |= 0x800;
} }
else if (sd->string == "MRK") else if (sd->string == "MRK" && !mShowMarkers)
// Marker objects. These are only visible in the // Marker objects. These are only visible in the
// editor. Until and unless we add an editor component to // editor.
// the engine, just skip this entire node. return;
isMarker = true;
} }
} }
if ( (isCollisionNode || (mShape->mAutogenerated && !raycasting)) if (isCollisionNode || (mShape->mAutogenerated && !raycasting))
&& (!isMarker || (!mShape->mAutogenerated && !raycasting)))
{ {
// NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape! // NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape!
// It must be ignored completely. // It must be ignored completely.
@ -319,7 +310,7 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
for(size_t i = 0;i < list.length();i++) for(size_t i = 0;i < list.length();i++)
{ {
if(!list[i].empty()) if(!list[i].empty())
handleNode(list[i].getPtr(), flags, isCollisionNode, raycasting, isMarker, isAnimated); handleNode(list[i].getPtr(), flags, isCollisionNode, raycasting, isAnimated);
} }
} }
} }
@ -374,10 +365,17 @@ void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int
TriangleMeshShape* childShape = new TriangleMeshShape(childMesh,true); TriangleMeshShape* childShape = new TriangleMeshShape(childMesh,true);
childShape->setLocalScaling(btVector3(transform[0][0], transform[1][1], transform[2][2])); float scale = shape->trafo.scale;
const Nif::Node* parent = shape;
while (parent->parent)
{
parent = parent->parent;
scale *= parent->trafo.scale;
}
Ogre::Quaternion q = transform.extractQuaternion(); Ogre::Quaternion q = transform.extractQuaternion();
Ogre::Vector3 v = transform.getTrans(); Ogre::Vector3 v = transform.getTrans();
childShape->setLocalScaling(btVector3(scale, scale, scale));
btTransform trans(btQuaternion(q.x, q.y, q.z, q.w), btVector3(v.x, v.y, v.z)); btTransform trans(btQuaternion(q.x, q.y, q.z, q.w), btVector3(v.x, v.y, v.z));
if (raycasting) if (raycasting)

@ -67,11 +67,12 @@ struct TriangleMeshShape : public btBvhTriangleMeshShape
class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader
{ {
public: public:
ManualBulletShapeLoader() ManualBulletShapeLoader(bool showMarkers=false)
: mShape(NULL) : mShape(NULL)
, mStaticMesh(NULL) , mStaticMesh(NULL)
, mCompoundShape(NULL) , mCompoundShape(NULL)
, mBoundingBox(NULL) , mBoundingBox(NULL)
, mShowMarkers(showMarkers)
{ {
} }
@ -107,7 +108,7 @@ private:
*Parse a node. *Parse a node.
*/ */
void handleNode(Nif::Node const *node, int flags, bool isCollisionNode, void handleNode(Nif::Node const *node, int flags, bool isCollisionNode,
bool raycasting, bool isMarker, bool isAnimated=false); bool raycasting, bool isAnimated=false);
/** /**
*Helper function *Helper function
@ -130,6 +131,8 @@ private:
btBoxShape *mBoundingBox; btBoxShape *mBoundingBox;
std::set<std::string> mControlledNodes; std::set<std::string> mControlledNodes;
bool mShowMarkers;
}; };

@ -689,6 +689,14 @@ public:
*/ */
class NIFObjectLoader class NIFObjectLoader
{ {
static bool sShowMarkers;
public:
static void setShowMarkers(bool show)
{
sShowMarkers = show;
}
private:
static void warn(const std::string &msg) static void warn(const std::string &msg)
{ {
std::cerr << "NIFObjectLoader: Warn: " << msg << std::endl; std::cerr << "NIFObjectLoader: Warn: " << msg << std::endl;
@ -1176,11 +1184,6 @@ class NIFObjectLoader
if(node->recType == Nif::RC_RootCollisionNode) if(node->recType == Nif::RC_RootCollisionNode)
isRootCollisionNode = true; isRootCollisionNode = true;
// Marker objects: just skip the entire node branch
/// \todo don't do this in the editor
if (node->name.find("marker") != std::string::npos)
return;
if(node->recType == Nif::RC_NiBSAnimationNode) if(node->recType == Nif::RC_NiBSAnimationNode)
animflags |= node->flags; animflags |= node->flags;
else if(node->recType == Nif::RC_NiBSParticleNode) else if(node->recType == Nif::RC_NiBSParticleNode)
@ -1213,7 +1216,7 @@ class NIFObjectLoader
const Nif::NiStringExtraData *sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr()); const Nif::NiStringExtraData *sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr());
// String markers may contain important information // String markers may contain important information
// affecting the entire subtree of this obj // affecting the entire subtree of this obj
if(sd->string == "MRK") if(sd->string == "MRK" && !sShowMarkers)
{ {
// Marker objects. These meshes are only visible in the // Marker objects. These meshes are only visible in the
// editor. // editor.
@ -1476,5 +1479,14 @@ void Loader::createKfControllers(Ogre::Entity *skelBase,
NIFObjectLoader::loadKf(skelBase->getSkeleton(), name, textKeys, ctrls); NIFObjectLoader::loadKf(skelBase->getSkeleton(), name, textKeys, ctrls);
} }
bool Loader::sShowMarkers = false;
bool NIFObjectLoader::sShowMarkers = false;
void Loader::setShowMarkers(bool show)
{
sShowMarkers = show;
NIFObjectLoader::setShowMarkers(show);
}
} // namespace NifOgre } // namespace NifOgre

@ -110,10 +110,18 @@ public:
std::string name, std::string name,
const std::string &group="General"); const std::string &group="General");
/// Set whether or not nodes marked as "MRK" should be shown.
/// These should be hidden ingame, but visible in the editior.
/// Default: false.
static void setShowMarkers(bool show);
static void createKfControllers(Ogre::Entity *skelBase, static void createKfControllers(Ogre::Entity *skelBase,
const std::string &name, const std::string &name,
TextKeyMap &textKeys, TextKeyMap &textKeys,
std::vector<Ogre::Controller<Ogre::Real> > &ctrls); std::vector<Ogre::Controller<Ogre::Real> > &ctrls);
private:
static bool sShowMarkers;
}; };
// FIXME: Should be with other general Ogre extensions. // FIXME: Should be with other general Ogre extensions.

@ -36,6 +36,9 @@ namespace ICS
, mDetectingBindingControl(NULL) , mDetectingBindingControl(NULL)
, mLog(log) , mLog(log)
, mXmouseAxisBinded(false), mYmouseAxisBinded(false) , mXmouseAxisBinded(false), mYmouseAxisBinded(false)
, mClientHeight(1)
, mClientWidth(1)
, mDetectingBindingDirection(Control::STOP)
{ {
ICS_LOG(" - Creating InputControlSystem - "); ICS_LOG(" - Creating InputControlSystem - ");

Loading…
Cancel
Save