forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'origin/master' into createfix
This commit is contained in:
commit
e4f341d4ba
15 changed files with 124 additions and 107 deletions
|
@ -278,8 +278,12 @@ namespace MWBase
|
|||
|
||||
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
|
||||
|
||||
virtual MWWorld::Ptr safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
|
||||
///< place an object in a "safe" location (ie not in the void, etc).
|
||||
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
|
||||
///< Place an object. Makes a copy of the Ptr.
|
||||
|
||||
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance) = 0;
|
||||
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
|
||||
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
|
||||
|
||||
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
|
||||
const = 0;
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace MWClass
|
|||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
MWWorld::ManualRef ref(store, id);
|
||||
ref.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition());
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
|
||||
customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId();
|
||||
customData.mSpawn = false;
|
||||
}
|
||||
|
|
|
@ -67,46 +67,29 @@ namespace MWGui
|
|||
{
|
||||
MWMechanics::Alchemy::Result result = mAlchemy->create (mNameEdit->getCaption ());
|
||||
|
||||
if (result == MWMechanics::Alchemy::Result_NoName)
|
||||
switch (result)
|
||||
{
|
||||
case MWMechanics::Alchemy::Result_NoName:
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage37}");
|
||||
return;
|
||||
}
|
||||
|
||||
// check if mortar & pestle is available (always needed)
|
||||
if (result == MWMechanics::Alchemy::Result_NoMortarAndPestle)
|
||||
{
|
||||
break;
|
||||
case MWMechanics::Alchemy::Result_NoMortarAndPestle:
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage45}");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure 2 or more ingredients were selected
|
||||
if (result == MWMechanics::Alchemy::Result_LessThanTwoIngredients)
|
||||
{
|
||||
break;
|
||||
case MWMechanics::Alchemy::Result_LessThanTwoIngredients:
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage6a}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == MWMechanics::Alchemy::Result_NoEffects)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}");
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == MWMechanics::Alchemy::Result_Success)
|
||||
{
|
||||
break;
|
||||
case MWMechanics::Alchemy::Result_Success:
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sPotionSuccess}");
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
|
||||
}
|
||||
else if (result == MWMechanics::Alchemy::Result_RandomFailure)
|
||||
{
|
||||
// potion failed
|
||||
break;
|
||||
case MWMechanics::Alchemy::Result_NoEffects:
|
||||
case MWMechanics::Alchemy::Result_RandomFailure:
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage8}");
|
||||
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
|
||||
break;
|
||||
}
|
||||
|
||||
// reduce count of the ingredients
|
||||
// remove ingredient slots that have been fully used up
|
||||
for (int i=0; i<4; ++i)
|
||||
if (mIngredients[i]->isUserString("ToolTipType"))
|
||||
{
|
||||
|
|
|
@ -114,31 +114,16 @@ namespace MWMechanics
|
|||
bool found = creatureMap.find(std::make_pair(it->first, it->second)) != creatureMap.end();
|
||||
if (!found)
|
||||
{
|
||||
ESM::Position ipos = mActor.getRefData().getPosition();
|
||||
osg::Vec3f pos(ipos.asVec3());
|
||||
|
||||
osg::Quat rot (-ipos.rot[2], osg::Vec3f(0,0,1));
|
||||
const float distance = 50;
|
||||
pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
|
||||
ipos.pos[0] = pos.x();
|
||||
ipos.pos[1] = pos.y();
|
||||
ipos.pos[2] = pos.z();
|
||||
ipos.rot[0] = 0;
|
||||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
const std::string& creatureGmst = summonMap[it->first];
|
||||
std::string creatureID =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(creatureGmst)->getString();
|
||||
|
||||
if (!creatureID.empty())
|
||||
{
|
||||
MWWorld::CellStore* store = mActor.getCell();
|
||||
int creatureActorId = -1;
|
||||
try
|
||||
{
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
||||
ref.getPtr().getCellRef().setPosition(ipos);
|
||||
|
||||
MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr());
|
||||
|
||||
|
@ -147,7 +132,7 @@ namespace MWMechanics
|
|||
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr());
|
||||
creatureActorId = summonedCreatureStats.getActorId();
|
||||
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), mActor, mActor.getCell(), 0, 120.f);
|
||||
|
||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(placed);
|
||||
if (anim)
|
||||
|
|
|
@ -1353,12 +1353,27 @@ namespace MWRender
|
|||
if (found != getNodeMap().end())
|
||||
{
|
||||
osg::MatrixTransform* node = found->second;
|
||||
|
||||
bool foundKeyframeCtrl = false;
|
||||
osg::Callback* cb = node->getUpdateCallback();
|
||||
while (cb)
|
||||
{
|
||||
if (dynamic_cast<NifOsg::KeyframeController*>(cb))
|
||||
{
|
||||
foundKeyframeCtrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundKeyframeCtrl)
|
||||
{
|
||||
mHeadController = new RotateController(mObjectRoot.get());
|
||||
node->addUpdateCallback(mHeadController);
|
||||
mActiveControllers.insert(std::make_pair(node, mHeadController));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::setHeadPitch(float pitchRadians)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <osg/Geometry>
|
||||
#include <osg/Material>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Depth>
|
||||
#include <osg/ClipNode>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/FrontFace>
|
||||
|
|
|
@ -434,7 +434,7 @@ namespace MWScript
|
|||
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
ref.getPtr().getCellRef().setPosition(pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
|
||||
placed.getClass().adjustPosition(placed, true);
|
||||
}
|
||||
}
|
||||
|
@ -482,7 +482,7 @@ namespace MWScript
|
|||
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
ref.getPtr().getCellRef().setPosition(pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,pos);
|
||||
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
|
||||
placed.getClass().adjustPosition(placed, true);
|
||||
}
|
||||
};
|
||||
|
@ -516,38 +516,10 @@ namespace MWScript
|
|||
|
||||
for (int i=0; i<count; ++i)
|
||||
{
|
||||
ESM::Position ipos = actor.getRefData().getPosition();
|
||||
osg::Vec3f pos(ipos.asVec3());
|
||||
osg::Quat rot(ipos.rot[2], osg::Vec3f(0,0,-1));
|
||||
if(direction == 0) pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
|
||||
else if(direction == 1) pos = pos - (rot * osg::Vec3f(0,1,0)) * distance;
|
||||
else if(direction == 2) pos = pos - (rot * osg::Vec3f(1,0,0)) * distance;
|
||||
else if(direction == 3) pos = pos + (rot * osg::Vec3f(1,0,0)) * distance;
|
||||
else throw std::runtime_error ("direction must be 0,1,2 or 3");
|
||||
|
||||
ipos.pos[0] = pos.x();
|
||||
ipos.pos[1] = pos.y();
|
||||
ipos.pos[2] = pos.z();
|
||||
|
||||
if (actor.getClass().isActor())
|
||||
{
|
||||
// TODO: should this depend on the 'direction' parameter?
|
||||
ipos.rot[0] = 0;
|
||||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ipos.rot[0] = actor.getRefData().getPosition().rot[0];
|
||||
ipos.rot[1] = actor.getRefData().getPosition().rot[1];
|
||||
ipos.rot[2] = actor.getRefData().getPosition().rot[2];
|
||||
}
|
||||
// create item
|
||||
MWWorld::CellStore* store = actor.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
|
||||
ref.getPtr().getCellRef().setPosition(ipos);
|
||||
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -268,6 +268,13 @@ namespace MWWorld
|
|||
mPhysics->addHeightField (data->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
worldsize / (verts-1), verts);
|
||||
}
|
||||
else
|
||||
{
|
||||
static std::vector<float> defaultHeight;
|
||||
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
|
||||
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
worldsize / (verts-1), verts);
|
||||
}
|
||||
}
|
||||
|
||||
// register local scripts
|
||||
|
|
|
@ -1325,11 +1325,50 @@ namespace MWWorld
|
|||
rotateObjectImp(ptr, osg::Vec3f(x, y, z), adjust);
|
||||
}
|
||||
|
||||
MWWorld::Ptr World::safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos)
|
||||
MWWorld::Ptr World::placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos)
|
||||
{
|
||||
return copyObjectToCell(ptr,cell,pos,ptr.getRefData().getCount(),false);
|
||||
}
|
||||
|
||||
MWWorld::Ptr World::safePlaceObject(const ConstPtr &ptr, const ConstPtr &referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance)
|
||||
{
|
||||
ESM::Position ipos = referenceObject.getRefData().getPosition();
|
||||
osg::Vec3f pos(ipos.asVec3());
|
||||
osg::Quat orientation(ipos.rot[2], osg::Vec3f(0,0,-1));
|
||||
|
||||
int fallbackDirections[4] = {direction, (direction+3)%4, (direction+2)%4, (direction+1)%4};
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
direction = fallbackDirections[i];
|
||||
// check if spawn point is safe, fall back to another direction if not
|
||||
osg::Vec3f spawnPoint = pos;
|
||||
if (direction == 0) spawnPoint = pos + (orientation * osg::Vec3f(0,1,0)) * distance;
|
||||
else if(direction == 1) spawnPoint = pos - (orientation * osg::Vec3f(0,1,0)) * distance;
|
||||
else if(direction == 2) spawnPoint = pos - (orientation * osg::Vec3f(1,0,0)) * distance;
|
||||
else if(direction == 3) spawnPoint = pos + (orientation * osg::Vec3f(1,0,0)) * distance;
|
||||
spawnPoint.z() += 30; // move up a little to account for slopes, will snap down later
|
||||
|
||||
if (!castRay(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(),
|
||||
pos.x(), pos.y(), pos.z() + 20))
|
||||
{
|
||||
// safe
|
||||
ipos.pos[0] = spawnPoint.x();
|
||||
ipos.pos[1] = spawnPoint.y();
|
||||
ipos.pos[2] = spawnPoint.z();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ipos.rot[0] = referenceObject.getRefData().getPosition().rot[0];
|
||||
ipos.rot[1] = referenceObject.getRefData().getPosition().rot[1];
|
||||
ipos.rot[2] = referenceObject.getRefData().getPosition().rot[2];
|
||||
|
||||
MWWorld::Ptr placed = copyObjectToCell(ptr, referenceCell, ipos, ptr.getRefData().getCount(), false);
|
||||
placed.getClass().adjustPosition(placed, true); // snap to ground
|
||||
return placed;
|
||||
}
|
||||
|
||||
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
|
@ -3025,23 +3064,9 @@ namespace MWWorld
|
|||
if (selectedCreature.empty())
|
||||
return;
|
||||
|
||||
ESM::Position ipos = mPlayer->getPlayer().getRefData().getPosition();
|
||||
osg::Vec3f pos(ipos.asVec3());
|
||||
osg::Quat rot(-ipos.rot[2], osg::Vec3f(0,0,1));
|
||||
const float distance = 50;
|
||||
pos = pos + (rot * osg::Vec3f(0,1,0)) * distance;
|
||||
ipos.pos[0] = pos.x();
|
||||
ipos.pos[1] = pos.y();
|
||||
ipos.pos[2] = pos.z();
|
||||
ipos.rot[0] = 0;
|
||||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
MWWorld::CellStore* cell = mPlayer->getPlayer().getCell();
|
||||
MWWorld::ManualRef ref(getStore(), selectedCreature, 1);
|
||||
ref.getPtr().getCellRef().setPosition(ipos);
|
||||
|
||||
safePlaceObject(ref.getPtr(), cell, ipos);
|
||||
safePlaceObject(ref.getPtr(), getPlayerPtr(), getPlayerPtr().getCell(), 0, 220.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -367,8 +367,12 @@ namespace MWWorld
|
|||
/// \param adjust indicates rotation should be set or adjusted
|
||||
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
|
||||
|
||||
virtual MWWorld::Ptr safePlaceObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
|
||||
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.
|
||||
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
|
||||
///< Place an object. Makes a copy of the Ptr.
|
||||
|
||||
virtual MWWorld::Ptr safePlaceObject (const MWWorld::ConstPtr& ptr, const MWWorld::ConstPtr& referenceObject, MWWorld::CellStore* referenceCell, int direction, float distance);
|
||||
///< Place an object in a safe place next to \a referenceObject. \a direction and \a distance specify the wanted placement
|
||||
/// relative to \a referenceObject (but the object may be placed somewhere else if the wanted location is obstructed).
|
||||
|
||||
virtual float getMaxActivationDistance();
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ struct Land
|
|||
DATA_VTEX = 16
|
||||
};
|
||||
|
||||
// default height to use in case there is no Land record
|
||||
static const int DEFAULT_HEIGHT = -2048;
|
||||
|
||||
// number of vertices per side
|
||||
static const int LAND_SIZE = 65;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
namespace ESMTerrain
|
||||
{
|
||||
|
||||
const float defaultHeight = -2048;
|
||||
const float defaultHeight = ESM::Land::DEFAULT_HEIGHT;
|
||||
|
||||
Storage::Storage(const VFS::Manager *vfs, const std::string& normalMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
|
||||
: mVFS(vfs)
|
||||
|
|
|
@ -56,10 +56,19 @@ namespace SceneUtil
|
|||
CopyRigVisitor copyVisitor(handle, filter);
|
||||
toAttach->accept(copyVisitor);
|
||||
|
||||
if (handle->getNumChildren() == 1)
|
||||
{
|
||||
osg::ref_ptr<osg::Node> newHandle = handle->getChild(0);
|
||||
handle->removeChild(newHandle);
|
||||
master->asGroup()->addChild(newHandle);
|
||||
return newHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
master->asGroup()->addChild(handle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FindByNameVisitor find(attachNode);
|
||||
|
|
|
@ -38,6 +38,8 @@ Skeleton::Skeleton()
|
|||
, mNeedToUpdateBoneMatrices(true)
|
||||
, mActive(true)
|
||||
, mLastFrameNumber(0)
|
||||
, mTraversedEvenFrame(false)
|
||||
, mTraversedOddFrame(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -48,6 +50,8 @@ Skeleton::Skeleton(const Skeleton ©, const osg::CopyOp ©op)
|
|||
, mNeedToUpdateBoneMatrices(true)
|
||||
, mActive(copy.mActive)
|
||||
, mLastFrameNumber(0)
|
||||
, mTraversedEvenFrame(false)
|
||||
, mTraversedOddFrame(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -111,6 +115,11 @@ void Skeleton::updateBoneMatrices(osg::NodeVisitor* nv)
|
|||
|
||||
mLastFrameNumber = nv->getTraversalNumber();
|
||||
|
||||
if (mLastFrameNumber % 2 == 0)
|
||||
mTraversedEvenFrame = true;
|
||||
else
|
||||
mTraversedOddFrame = true;
|
||||
|
||||
if (mNeedToUpdateBoneMatrices)
|
||||
{
|
||||
if (mRootBone.get())
|
||||
|
@ -140,7 +149,7 @@ void Skeleton::traverse(osg::NodeVisitor& nv)
|
|||
if (!getActive() && nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR
|
||||
// need to process at least 2 frames before shutting off update, since we need to have both frame-alternating RigGeometries initialized
|
||||
// this would be more naturally handled if the double-buffering was implemented in RigGeometry itself rather than in a FrameSwitch decorator node
|
||||
&& mLastFrameNumber != 0 && mLastFrameNumber+2 <= nv.getTraversalNumber())
|
||||
&& mLastFrameNumber != 0 && mTraversedEvenFrame && mTraversedOddFrame)
|
||||
return;
|
||||
osg::Group::traverse(nv);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ namespace SceneUtil
|
|||
bool mActive;
|
||||
|
||||
unsigned int mLastFrameNumber;
|
||||
bool mTraversedEvenFrame;
|
||||
bool mTraversedOddFrame;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue