|
|
|
@ -228,6 +228,7 @@ namespace MWWorld
|
|
|
|
|
|
|
|
|
|
mCells.clear();
|
|
|
|
|
|
|
|
|
|
mMagicBolts.clear();
|
|
|
|
|
mProjectiles.clear();
|
|
|
|
|
mDoorStates.clear();
|
|
|
|
|
|
|
|
|
@ -821,7 +822,7 @@ namespace MWWorld
|
|
|
|
|
const ESM::Position &posdata = ptr.getRefData().getPosition();
|
|
|
|
|
Ogre::Vector3 pos(posdata.pos);
|
|
|
|
|
Ogre::Quaternion rot = Ogre::Quaternion(Ogre::Radian(posdata.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(posdata.rot[0]), Ogre::Vector3::UNIT_X);
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(posdata.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
|
|
|
|
|
|
|
|
|
|
MWRender::Animation *anim = mRendering->getAnimation(ptr);
|
|
|
|
|
if(anim != NULL)
|
|
|
|
@ -858,7 +859,7 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z)
|
|
|
|
|
void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
|
|
|
|
|
{
|
|
|
|
|
ESM::Position &pos = ptr.getRefData().getPosition();
|
|
|
|
|
|
|
|
|
@ -872,27 +873,27 @@ namespace MWWorld
|
|
|
|
|
bool isPlayer = ptr == mPlayer->getPlayer();
|
|
|
|
|
bool haveToMove = isPlayer || mWorldScene->isCellActive(*currCell);
|
|
|
|
|
|
|
|
|
|
if (*currCell != newCell)
|
|
|
|
|
if (currCell != newCell)
|
|
|
|
|
{
|
|
|
|
|
removeContainerScripts(ptr);
|
|
|
|
|
|
|
|
|
|
if (isPlayer)
|
|
|
|
|
{
|
|
|
|
|
if (!newCell.isExterior())
|
|
|
|
|
changeToInteriorCell(Misc::StringUtils::lowerCase(newCell.getCell()->mName), pos);
|
|
|
|
|
if (!newCell->isExterior())
|
|
|
|
|
changeToInteriorCell(Misc::StringUtils::lowerCase(newCell->getCell()->mName), pos);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int cellX = newCell.getCell()->getGridX();
|
|
|
|
|
int cellY = newCell.getCell()->getGridY();
|
|
|
|
|
int cellX = newCell->getCell()->getGridX();
|
|
|
|
|
int cellY = newCell->getCell()->getGridY();
|
|
|
|
|
mWorldScene->changeCell(cellX, cellY, pos, false);
|
|
|
|
|
}
|
|
|
|
|
addContainerScripts (getPlayerPtr(), &newCell);
|
|
|
|
|
addContainerScripts (getPlayerPtr(), newCell);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!mWorldScene->isCellActive(*currCell))
|
|
|
|
|
copyObjectToCell(ptr, newCell, pos);
|
|
|
|
|
else if (!mWorldScene->isCellActive(newCell))
|
|
|
|
|
ptr.getClass().copyToCell(ptr, *newCell, pos);
|
|
|
|
|
else if (!mWorldScene->isCellActive(*newCell))
|
|
|
|
|
{
|
|
|
|
|
mWorldScene->removeObjectFromScene(ptr);
|
|
|
|
|
mLocalScripts.remove(ptr);
|
|
|
|
@ -900,7 +901,7 @@ namespace MWWorld
|
|
|
|
|
haveToMove = false;
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr newPtr = MWWorld::Class::get(ptr)
|
|
|
|
|
.copyToCell(ptr, newCell);
|
|
|
|
|
.copyToCell(ptr, *newCell);
|
|
|
|
|
newPtr.getRefData().setBaseNode(0);
|
|
|
|
|
|
|
|
|
|
objectLeftActiveCell(ptr, newPtr);
|
|
|
|
@ -908,7 +909,7 @@ namespace MWWorld
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MWWorld::Ptr copy =
|
|
|
|
|
MWWorld::Class::get(ptr).copyToCell(ptr, newCell, pos);
|
|
|
|
|
MWWorld::Class::get(ptr).copyToCell(ptr, *newCell, pos);
|
|
|
|
|
|
|
|
|
|
mRendering->updateObjectCell(ptr, copy);
|
|
|
|
|
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy);
|
|
|
|
@ -923,7 +924,7 @@ namespace MWWorld
|
|
|
|
|
mLocalScripts.remove(ptr);
|
|
|
|
|
removeContainerScripts (ptr);
|
|
|
|
|
mLocalScripts.add(script, copy);
|
|
|
|
|
addContainerScripts (copy, &newCell);
|
|
|
|
|
addContainerScripts (copy, newCell);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ptr.getRefData().setCount(0);
|
|
|
|
@ -947,7 +948,7 @@ namespace MWWorld
|
|
|
|
|
cell = getExterior(cellX, cellY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
moveObject(ptr, *cell, x, y, z);
|
|
|
|
|
moveObject(ptr, cell, x, y, z);
|
|
|
|
|
|
|
|
|
|
return cell != ptr.getCell();
|
|
|
|
|
}
|
|
|
|
@ -1041,15 +1042,13 @@ namespace MWWorld
|
|
|
|
|
while(ptr.getRefData().getLocalRotation().rot[2]<=-fullRotateRad)
|
|
|
|
|
ptr.getRefData().getLocalRotation().rot[2]+=fullRotateRad;
|
|
|
|
|
|
|
|
|
|
float *worldRot = ptr.getRefData().getPosition().rot;
|
|
|
|
|
Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z));
|
|
|
|
|
|
|
|
|
|
Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(-worldRot[0]), Ogre::Vector3::UNIT_X)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(-worldRot[1]), Ogre::Vector3::UNIT_Y)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(-worldRot[2]), Ogre::Vector3::UNIT_Z));
|
|
|
|
|
|
|
|
|
|
Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-x).valueRadians()), Ogre::Vector3::UNIT_X)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-y).valueRadians()), Ogre::Vector3::UNIT_Y)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-z).valueRadians()), Ogre::Vector3::UNIT_Z));
|
|
|
|
|
Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*
|
|
|
|
|
Ogre::Quaternion(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z));
|
|
|
|
|
|
|
|
|
|
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
|
|
|
|
|
mPhysics->rotateObject(ptr);
|
|
|
|
@ -1080,7 +1079,7 @@ namespace MWWorld
|
|
|
|
|
pos.z = traced.z;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
moveObject(ptr, *ptr.getCell(), pos.x, pos.y, pos.z);
|
|
|
|
|
moveObject(ptr, ptr.getCell(), pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
|
|
|
|
@ -1091,9 +1090,9 @@ namespace MWWorld
|
|
|
|
|
adjust);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos)
|
|
|
|
|
MWWorld::Ptr World::safePlaceObject(const MWWorld::Ptr& ptr, MWWorld::CellStore* cell, ESM::Position pos)
|
|
|
|
|
{
|
|
|
|
|
return copyObjectToCell(ptr,Cell,pos,false);
|
|
|
|
|
return copyObjectToCell(ptr,cell,pos,false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
|
|
|
|
@ -1127,6 +1126,7 @@ namespace MWWorld
|
|
|
|
|
{
|
|
|
|
|
processDoors(duration);
|
|
|
|
|
|
|
|
|
|
moveMagicBolts(duration);
|
|
|
|
|
moveProjectiles(duration);
|
|
|
|
|
|
|
|
|
|
const PtrVelocityList &results = mPhysics->applyQueuedMovement(duration);
|
|
|
|
@ -1506,15 +1506,7 @@ namespace MWWorld
|
|
|
|
|
if (!result.first)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
CellStore* cell;
|
|
|
|
|
if (isCellExterior())
|
|
|
|
|
{
|
|
|
|
|
int cellX, cellY;
|
|
|
|
|
positionToIndex(result.second[0], result.second[1], cellX, cellY);
|
|
|
|
|
cell = mCells.getExterior(cellX, cellY);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cell = getPlayerPtr().getCell();
|
|
|
|
|
CellStore* cell = getPlayerPtr().getCell();
|
|
|
|
|
|
|
|
|
|
ESM::Position pos = getPlayerPtr().getRefData().getPosition();
|
|
|
|
|
pos.pos[0] = result.second[0];
|
|
|
|
@ -1527,7 +1519,7 @@ namespace MWWorld
|
|
|
|
|
// copy the object and set its count
|
|
|
|
|
int origCount = object.getRefData().getCount();
|
|
|
|
|
object.getRefData().setCount(amount);
|
|
|
|
|
Ptr dropped = copyObjectToCell(object, *cell, pos, true);
|
|
|
|
|
Ptr dropped = copyObjectToCell(object, cell, pos, true);
|
|
|
|
|
object.getRefData().setCount(origCount);
|
|
|
|
|
|
|
|
|
|
// only the player place items in the world, so no need to check actor
|
|
|
|
@ -1548,7 +1540,7 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ptr World::copyObjectToCell(const Ptr &object, CellStore &cell, ESM::Position pos, bool adjustPos)
|
|
|
|
|
Ptr World::copyObjectToCell(const Ptr &object, CellStore* cell, ESM::Position pos, bool adjustPos)
|
|
|
|
|
{
|
|
|
|
|
if (object.getClass().isActor() || adjustPos)
|
|
|
|
|
{
|
|
|
|
@ -1560,17 +1552,17 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cell.isExterior())
|
|
|
|
|
if (cell->isExterior())
|
|
|
|
|
{
|
|
|
|
|
int cellX, cellY;
|
|
|
|
|
positionToIndex(pos.pos[0], pos.pos[1], cellX, cellY);
|
|
|
|
|
cell = *mCells.getExterior(cellX, cellY);
|
|
|
|
|
cell = mCells.getExterior(cellX, cellY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr dropped =
|
|
|
|
|
MWWorld::Class::get(object).copyToCell(object, cell, pos);
|
|
|
|
|
MWWorld::Class::get(object).copyToCell(object, *cell, pos);
|
|
|
|
|
|
|
|
|
|
if (mWorldScene->isCellActive(cell)) {
|
|
|
|
|
if (mWorldScene->isCellActive(*cell)) {
|
|
|
|
|
if (dropped.getRefData().isEnabled()) {
|
|
|
|
|
mWorldScene->addObjectToScene(dropped);
|
|
|
|
|
}
|
|
|
|
@ -1578,7 +1570,7 @@ namespace MWWorld
|
|
|
|
|
if (!script.empty()) {
|
|
|
|
|
mLocalScripts.add(script, dropped);
|
|
|
|
|
}
|
|
|
|
|
addContainerScripts(dropped, &cell);
|
|
|
|
|
addContainerScripts(dropped, cell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dropped;
|
|
|
|
@ -1608,7 +1600,7 @@ namespace MWWorld
|
|
|
|
|
// copy the object and set its count
|
|
|
|
|
int origCount = object.getRefData().getCount();
|
|
|
|
|
object.getRefData().setCount(amount);
|
|
|
|
|
Ptr dropped = copyObjectToCell(object, *cell, pos);
|
|
|
|
|
Ptr dropped = copyObjectToCell(object, cell, pos);
|
|
|
|
|
object.getRefData().setCount(origCount);
|
|
|
|
|
|
|
|
|
|
if(actor == mPlayer->getPlayer()) // Only call if dropped by player
|
|
|
|
@ -2143,7 +2135,37 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
|
|
|
|
|
void World::launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
|
|
|
|
|
const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed)
|
|
|
|
|
{
|
|
|
|
|
ProjectileState state;
|
|
|
|
|
state.mActorHandle = actor.getRefData().getHandle();
|
|
|
|
|
state.mBow = bow;
|
|
|
|
|
state.mSpeed = speed;
|
|
|
|
|
|
|
|
|
|
MWWorld::ManualRef ref(getStore(), projectile.getCellRef().mRefID);
|
|
|
|
|
|
|
|
|
|
ESM::Position pos;
|
|
|
|
|
pos.pos[0] = worldPos.x;
|
|
|
|
|
pos.pos[1] = worldPos.y;
|
|
|
|
|
pos.pos[2] = worldPos.z;
|
|
|
|
|
|
|
|
|
|
// Do NOT copy actor rotation! actors use a different rotation order, and this will not produce the same facing direction.
|
|
|
|
|
Ogre::Matrix3 mat;
|
|
|
|
|
orient.ToRotationMatrix(mat);
|
|
|
|
|
Ogre::Radian xr,yr,zr;
|
|
|
|
|
mat.ToEulerAnglesXYZ(xr, yr, zr);
|
|
|
|
|
pos.rot[0] = -xr.valueRadians();
|
|
|
|
|
pos.rot[1] = -yr.valueRadians();
|
|
|
|
|
pos.rot[2] = -zr.valueRadians();
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr ptr = copyObjectToCell(ref.getPtr(), actor.getCell(), pos, false);
|
|
|
|
|
ptr.getRefData().setCount(1);
|
|
|
|
|
|
|
|
|
|
mProjectiles[ptr] = state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::launchMagicBolt (const std::string& id, bool stack, const ESM::EffectList& effects,
|
|
|
|
|
const MWWorld::Ptr& actor, const std::string& sourceName)
|
|
|
|
|
{
|
|
|
|
|
std::string projectileModel;
|
|
|
|
@ -2185,13 +2207,23 @@ namespace MWWorld
|
|
|
|
|
pos.pos[0] = actor.getRefData().getPosition().pos[0];
|
|
|
|
|
pos.pos[1] = actor.getRefData().getPosition().pos[1];
|
|
|
|
|
pos.pos[2] = actor.getRefData().getPosition().pos[2] + height;
|
|
|
|
|
pos.rot[0] = actor.getRefData().getPosition().rot[0];
|
|
|
|
|
pos.rot[1] = actor.getRefData().getPosition().rot[1];
|
|
|
|
|
pos.rot[2] = actor.getRefData().getPosition().rot[2];
|
|
|
|
|
|
|
|
|
|
// Do NOT copy rotation directly! actors use a different rotation order, and this will not produce the same facing direction.
|
|
|
|
|
Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
|
|
|
|
Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
|
|
|
|
|
Ogre::Matrix3 mat;
|
|
|
|
|
orient.ToRotationMatrix(mat);
|
|
|
|
|
Ogre::Radian xr,yr,zr;
|
|
|
|
|
mat.ToEulerAnglesXYZ(xr, yr, zr);
|
|
|
|
|
pos.rot[0] = -xr.valueRadians();
|
|
|
|
|
pos.rot[1] = -yr.valueRadians();
|
|
|
|
|
pos.rot[2] = -zr.valueRadians();
|
|
|
|
|
|
|
|
|
|
ref.getPtr().getCellRef().mPos = pos;
|
|
|
|
|
MWWorld::Ptr ptr = copyObjectToCell(ref.getPtr(), *actor.getCell(), pos);
|
|
|
|
|
CellStore* cell = actor.getCell();
|
|
|
|
|
MWWorld::Ptr ptr = copyObjectToCell(ref.getPtr(), cell, pos);
|
|
|
|
|
|
|
|
|
|
ProjectileState state;
|
|
|
|
|
MagicBoltState state;
|
|
|
|
|
state.mSourceName = sourceName;
|
|
|
|
|
state.mId = id;
|
|
|
|
|
state.mActorHandle = actor.getRefData().getHandle();
|
|
|
|
@ -2209,7 +2241,7 @@ namespace MWWorld
|
|
|
|
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
|
|
|
|
sndMgr->playSound3D(ptr, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
|
|
|
|
|
|
|
|
|
|
mProjectiles[ptr] = state;
|
|
|
|
|
mMagicBolts[ptr] = state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::moveProjectiles(float duration)
|
|
|
|
@ -2226,13 +2258,100 @@ namespace MWWorld
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr ptr = it->first;
|
|
|
|
|
|
|
|
|
|
Ogre::Vector3 rot(ptr.getRefData().getPosition().rot);
|
|
|
|
|
Ogre::Quaternion orient = ptr.getRefData().getBaseNode()->getOrientation();
|
|
|
|
|
|
|
|
|
|
// TODO: Why -rot.z, but not -rot.x? (note: same issue in MovementSolver::move)
|
|
|
|
|
Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z);
|
|
|
|
|
orient = orient * Ogre::Quaternion(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X);
|
|
|
|
|
float speed = it->second.mSpeed;
|
|
|
|
|
|
|
|
|
|
Ogre::Vector3 direction = orient.yAxis();
|
|
|
|
|
direction.normalise();
|
|
|
|
|
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
|
|
|
|
|
Ogre::Vector3 newPos = pos + direction * duration * speed;
|
|
|
|
|
|
|
|
|
|
// Check for impact
|
|
|
|
|
btVector3 from(pos.x, pos.y, pos.z);
|
|
|
|
|
btVector3 to(newPos.x, newPos.y, newPos.z);
|
|
|
|
|
std::vector<std::pair<float, std::string> > collisions = mPhysEngine->rayTest2(from, to);
|
|
|
|
|
bool hit=false;
|
|
|
|
|
|
|
|
|
|
// HACK: query against the shape as well, since the ray does not take the volume into account
|
|
|
|
|
// really, this should be a convex cast, but the whole physics system needs a rewrite
|
|
|
|
|
std::vector<std::string> col2 = mPhysEngine->getCollisions(ptr.getRefData().getHandle());
|
|
|
|
|
for (std::vector<std::string>::iterator ci = col2.begin(); ci != col2.end(); ++ci)
|
|
|
|
|
collisions.push_back(std::make_pair(0.f,*ci));
|
|
|
|
|
|
|
|
|
|
for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt)
|
|
|
|
|
{
|
|
|
|
|
MWWorld::Ptr obstacle = searchPtrViaHandle(cIt->second);
|
|
|
|
|
if (obstacle == ptr)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle);
|
|
|
|
|
|
|
|
|
|
// Arrow intersects with player immediately after shooting :/
|
|
|
|
|
if (obstacle == caster)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (caster.isEmpty())
|
|
|
|
|
caster = obstacle;
|
|
|
|
|
|
|
|
|
|
if (obstacle.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
// Terrain
|
|
|
|
|
}
|
|
|
|
|
else if (obstacle.getClass().isActor())
|
|
|
|
|
{
|
|
|
|
|
// Fargoth
|
|
|
|
|
obstacle.getClass().getCreatureStats(obstacle).setHealth(0);
|
|
|
|
|
}
|
|
|
|
|
hit = true;
|
|
|
|
|
}
|
|
|
|
|
if (hit)
|
|
|
|
|
{
|
|
|
|
|
mProjectiles.erase(it++);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string handle = ptr.getRefData().getHandle();
|
|
|
|
|
|
|
|
|
|
moveObject(ptr, newPos.x, newPos.y, newPos.z);
|
|
|
|
|
|
|
|
|
|
// HACK: Re-fetch Ptrs if necessary, since the cell might have changed
|
|
|
|
|
if (!ptr.getRefData().getCount())
|
|
|
|
|
{
|
|
|
|
|
moved[handle] = it->second;
|
|
|
|
|
mProjectiles.erase(it++);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HACK: Re-fetch Ptrs if necessary, since the cell might have changed
|
|
|
|
|
for (std::map<std::string, ProjectileState>::iterator it = moved.begin(); it != moved.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
MWWorld::Ptr newPtr = searchPtrViaHandle(it->first);
|
|
|
|
|
if (newPtr.isEmpty()) // The projectile went into an inactive cell and was deleted
|
|
|
|
|
continue;
|
|
|
|
|
mProjectiles[getPtrViaHandle(it->first)] = it->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::moveMagicBolts(float duration)
|
|
|
|
|
{
|
|
|
|
|
std::map<std::string, MagicBoltState> moved;
|
|
|
|
|
for (std::map<MWWorld::Ptr, MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end();)
|
|
|
|
|
{
|
|
|
|
|
if (!mWorldScene->isCellActive(*it->first.getCell()))
|
|
|
|
|
{
|
|
|
|
|
deleteObject(it->first);
|
|
|
|
|
mMagicBolts.erase(it++);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr ptr = it->first;
|
|
|
|
|
|
|
|
|
|
Ogre::Vector3 rot(ptr.getRefData().getPosition().rot);
|
|
|
|
|
|
|
|
|
|
Ogre::Quaternion orient = ptr.getRefData().getBaseNode()->getOrientation();
|
|
|
|
|
static float fTargetSpellMaxSpeed = getStore().get<ESM::GameSetting>().find("fTargetSpellMaxSpeed")->getFloat();
|
|
|
|
|
float speed = fTargetSpellMaxSpeed * it->second.mSpeed;
|
|
|
|
|
|
|
|
|
@ -2279,7 +2398,7 @@ namespace MWWorld
|
|
|
|
|
explodeSpell(Ogre::Vector3(ptr.getRefData().getPosition().pos), ptr, it->second.mEffects, caster, it->second.mId, it->second.mSourceName);
|
|
|
|
|
|
|
|
|
|
deleteObject(ptr);
|
|
|
|
|
mProjectiles.erase(it++);
|
|
|
|
|
mMagicBolts.erase(it++);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2291,29 +2410,29 @@ namespace MWWorld
|
|
|
|
|
if (!ptr.getRefData().getCount())
|
|
|
|
|
{
|
|
|
|
|
moved[handle] = it->second;
|
|
|
|
|
mProjectiles.erase(it++);
|
|
|
|
|
mMagicBolts.erase(it++);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HACK: Re-fetch Ptrs if necessary, since the cell might have changed
|
|
|
|
|
for (std::map<std::string, ProjectileState>::iterator it = moved.begin(); it != moved.end(); ++it)
|
|
|
|
|
for (std::map<std::string, MagicBoltState>::iterator it = moved.begin(); it != moved.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
MWWorld::Ptr newPtr = searchPtrViaHandle(it->first);
|
|
|
|
|
if (newPtr.isEmpty()) // The projectile went into an inactive cell and was deleted
|
|
|
|
|
continue;
|
|
|
|
|
mProjectiles[getPtrViaHandle(it->first)] = it->second;
|
|
|
|
|
mMagicBolts[getPtrViaHandle(it->first)] = it->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::objectLeftActiveCell(Ptr object, Ptr movedPtr)
|
|
|
|
|
{
|
|
|
|
|
// For now, projectiles moved to an inactive cell are just deleted, because there's no reliable way to hold on to the meta information
|
|
|
|
|
if (mMagicBolts.find(object) != mMagicBolts.end())
|
|
|
|
|
deleteObject(movedPtr);
|
|
|
|
|
if (mProjectiles.find(object) != mProjectiles.end())
|
|
|
|
|
{
|
|
|
|
|
deleteObject(movedPtr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::vector<std::string>& World::getContentFiles() const
|
|
|
|
@ -2650,7 +2769,7 @@ namespace MWWorld
|
|
|
|
|
MWWorld::ManualRef ref(getStore(), selectedCreature, 1);
|
|
|
|
|
ref.getPtr().getCellRef().mPos = ipos;
|
|
|
|
|
|
|
|
|
|
safePlaceObject(ref.getPtr(),*cell,ipos);
|
|
|
|
|
safePlaceObject(ref.getPtr(), cell, ipos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|