mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-04 07:15:34 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
640d473866
13 changed files with 121 additions and 56 deletions
|
@ -15,7 +15,7 @@
|
|||
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
|
||||
|
||||
#include <components/ogreinit/ogreinit.hpp>
|
||||
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
#include <components/bsa/resources.hpp>
|
||||
|
||||
#include "model/doc/document.hpp"
|
||||
|
@ -35,6 +35,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
|
||||
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
|
||||
|
||||
NifOgre::Loader::setShowMarkers(true);
|
||||
|
||||
mOverlaySystem.reset (new CSVRender::OverlaySystem);
|
||||
|
||||
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace CSVWorld
|
|||
PhysicsSystem::PhysicsSystem()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
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)
|
||||
{
|
||||
if (bound)
|
||||
|
@ -1101,12 +1107,12 @@ namespace MWMechanics
|
|||
updateCrimePersuit(iter->first, duration);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
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)
|
||||
{
|
||||
if(actor != MWBase::Environment::get().getWorld()->getPlayerPtr()
|
||||
&& !actor.getClass().getCreatureStats(actor).getKnockedDown())
|
||||
if(actor != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
{
|
||||
if (!mPackages.empty())
|
||||
{
|
||||
|
|
|
@ -308,22 +308,26 @@ namespace MWMechanics
|
|||
// Play idle voiced dialogue entries randomly
|
||||
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
||||
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();
|
||||
|
||||
// Don't bother if the player is out of hearing range
|
||||
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
||||
.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
|
||||
// A bit counterintuitive, likely vanilla did this to reduce the appearance of
|
||||
// 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().getDialogueManager()->say(actor, "idle");
|
||||
}
|
||||
|
|
|
@ -70,13 +70,15 @@ void animateCollisionShapes (std::map<OEngine::Physic::RigidBody*, OEngine::Phys
|
|||
if (bone == NULL)
|
||||
continue;
|
||||
|
||||
btCompoundShape* compound = dynamic_cast<btCompoundShape*>(instance.mCompound);
|
||||
btCompoundShape* compound = static_cast<btCompoundShape*>(instance.mCompound);
|
||||
|
||||
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()));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -348,6 +350,8 @@ namespace MWWorld
|
|||
velocity *= 1.f-(fStromWalkMult * (angle.valueDegrees()/180.f));
|
||||
}
|
||||
|
||||
Ogre::Vector3 origVelocity = velocity;
|
||||
|
||||
Ogre::Vector3 newPosition = position;
|
||||
/*
|
||||
* A loop to find newPosition using tracer, if successful different from the starting position.
|
||||
|
@ -425,10 +429,18 @@ namespace MWWorld
|
|||
else
|
||||
{
|
||||
// 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);
|
||||
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
|
||||
// care of that.
|
||||
|
|
|
@ -21,6 +21,18 @@
|
|||
|
||||
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,
|
||||
MWRender::RenderingManager& rendering)
|
||||
{
|
||||
|
@ -80,10 +92,7 @@ namespace
|
|||
{
|
||||
try
|
||||
{
|
||||
const std::string& model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr));
|
||||
mRendering.addObject(ptr, model);
|
||||
ptr.getClass().insertObject (ptr, model, mPhysics);
|
||||
|
||||
addObject(ptr, mPhysics, mRendering);
|
||||
updateObjectLocalRotation(ptr, mPhysics, mRendering);
|
||||
if (ptr.getRefData().getBaseNode())
|
||||
{
|
||||
|
@ -530,9 +539,7 @@ namespace MWWorld
|
|||
|
||||
void Scene::addObjectToScene (const Ptr& ptr)
|
||||
{
|
||||
const std::string& model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr));
|
||||
mRendering.addObject(ptr, model);
|
||||
ptr.getClass().insertObject (ptr, model, *mPhysics);
|
||||
addObject(ptr, *mPhysics, mRendering);
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
|
||||
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
|
||||
}
|
||||
|
|
|
@ -2107,6 +2107,9 @@ namespace MWWorld
|
|||
Ogre::Vector3 playerPos(refdata.getPosition().pos);
|
||||
|
||||
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))
|
||||
return 2;
|
||||
if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) ||
|
||||
|
@ -2326,9 +2329,15 @@ namespace MWWorld
|
|||
if (!targetActor.getRefData().getBaseNode() || !targetActor.getRefData().getBaseNode())
|
||||
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;
|
||||
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetActor.getRefData().getHandle())->getHalfExtents();
|
||||
Ogre::Vector3 halfExt2 = actor2->getHalfExtents();
|
||||
const float* pos2 = targetActor.getRefData().getPosition().pos;
|
||||
|
||||
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);
|
||||
|
||||
//do a first pass
|
||||
handleNode(node,0,false,false,false);
|
||||
handleNode(node,0,false,false);
|
||||
|
||||
if(mBoundingBox != NULL)
|
||||
{
|
||||
|
@ -232,7 +232,7 @@ bool ManualBulletShapeLoader::hasAutoGeneratedCollision(Nif::Node const * rootNo
|
|||
|
||||
void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags,
|
||||
bool isCollisionNode,
|
||||
bool raycasting, bool isMarker, bool isAnimated)
|
||||
bool raycasting, bool isAnimated)
|
||||
{
|
||||
// Accumulate the flags from all the child nodes. This works for all
|
||||
// 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)
|
||||
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
|
||||
Nif::Extra const *e = node;
|
||||
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.
|
||||
flags |= 0x800;
|
||||
}
|
||||
else if (sd->string == "MRK")
|
||||
else if (sd->string == "MRK" && !mShowMarkers)
|
||||
// Marker objects. These are only visible in the
|
||||
// editor. Until and unless we add an editor component to
|
||||
// the engine, just skip this entire node.
|
||||
isMarker = true;
|
||||
// editor.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (isCollisionNode || (mShape->mAutogenerated && !raycasting))
|
||||
&& (!isMarker || (!mShape->mAutogenerated && !raycasting)))
|
||||
if (isCollisionNode || (mShape->mAutogenerated && !raycasting))
|
||||
{
|
||||
// NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape!
|
||||
// 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++)
|
||||
{
|
||||
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);
|
||||
|
||||
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::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));
|
||||
|
||||
if (raycasting)
|
||||
|
|
|
@ -67,11 +67,12 @@ struct TriangleMeshShape : public btBvhTriangleMeshShape
|
|||
class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader
|
||||
{
|
||||
public:
|
||||
ManualBulletShapeLoader()
|
||||
ManualBulletShapeLoader(bool showMarkers=false)
|
||||
: mShape(NULL)
|
||||
, mStaticMesh(NULL)
|
||||
, mCompoundShape(NULL)
|
||||
, mBoundingBox(NULL)
|
||||
, mShowMarkers(showMarkers)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -107,7 +108,7 @@ private:
|
|||
*Parse a node.
|
||||
*/
|
||||
void handleNode(Nif::Node const *node, int flags, bool isCollisionNode,
|
||||
bool raycasting, bool isMarker, bool isAnimated=false);
|
||||
bool raycasting, bool isAnimated=false);
|
||||
|
||||
/**
|
||||
*Helper function
|
||||
|
@ -130,6 +131,8 @@ private:
|
|||
btBoxShape *mBoundingBox;
|
||||
|
||||
std::set<std::string> mControlledNodes;
|
||||
|
||||
bool mShowMarkers;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -689,6 +689,14 @@ public:
|
|||
*/
|
||||
class NIFObjectLoader
|
||||
{
|
||||
static bool sShowMarkers;
|
||||
public:
|
||||
static void setShowMarkers(bool show)
|
||||
{
|
||||
sShowMarkers = show;
|
||||
}
|
||||
private:
|
||||
|
||||
static void warn(const std::string &msg)
|
||||
{
|
||||
std::cerr << "NIFObjectLoader: Warn: " << msg << std::endl;
|
||||
|
@ -1176,11 +1184,6 @@ class NIFObjectLoader
|
|||
if(node->recType == Nif::RC_RootCollisionNode)
|
||||
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)
|
||||
animflags |= node->flags;
|
||||
else if(node->recType == Nif::RC_NiBSParticleNode)
|
||||
|
@ -1213,7 +1216,7 @@ class NIFObjectLoader
|
|||
const Nif::NiStringExtraData *sd = static_cast<const Nif::NiStringExtraData*>(e.getPtr());
|
||||
// String markers may contain important information
|
||||
// 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
|
||||
// editor.
|
||||
|
@ -1476,5 +1479,14 @@ void Loader::createKfControllers(Ogre::Entity *skelBase,
|
|||
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
|
||||
|
|
|
@ -110,10 +110,18 @@ public:
|
|||
std::string name,
|
||||
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,
|
||||
const std::string &name,
|
||||
TextKeyMap &textKeys,
|
||||
std::vector<Ogre::Controller<Ogre::Real> > &ctrls);
|
||||
|
||||
private:
|
||||
static bool sShowMarkers;
|
||||
};
|
||||
|
||||
// FIXME: Should be with other general Ogre extensions.
|
||||
|
|
3
extern/oics/ICSInputControlSystem.cpp
vendored
3
extern/oics/ICSInputControlSystem.cpp
vendored
|
@ -36,6 +36,9 @@ namespace ICS
|
|||
, mDetectingBindingControl(NULL)
|
||||
, mLog(log)
|
||||
, mXmouseAxisBinded(false), mYmouseAxisBinded(false)
|
||||
, mClientHeight(1)
|
||||
, mClientWidth(1)
|
||||
, mDetectingBindingDirection(Control::STOP)
|
||||
{
|
||||
ICS_LOG(" - Creating InputControlSystem - ");
|
||||
|
||||
|
|
Loading…
Reference in a new issue