mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +00:00
parent
290da132b1
commit
c3ef387208
14 changed files with 128 additions and 54 deletions
|
@ -231,15 +231,16 @@ namespace MWBase
|
|||
|
||||
virtual float getTimeScaleFactor() const = 0;
|
||||
|
||||
virtual void changeToInteriorCell (const std::string& cellName,
|
||||
const ESM::Position& position) = 0;
|
||||
virtual void changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool changeEvent=true) = 0;
|
||||
///< Move to interior cell.
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
||||
virtual void changeToExteriorCell (const ESM::Position& position, bool changeEvent=true) = 0;
|
||||
///< Move to exterior cell.
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true) = 0;
|
||||
///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool changeEvent=true) = 0;
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
|
|
@ -759,7 +759,18 @@ namespace MWClass
|
|||
|
||||
void Creature::respawn(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
if (isFlagBitSet(ptr, ESM::Creature::Respawn))
|
||||
const MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
|
||||
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
||||
return;
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
||||
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||
|
||||
float delay = ptr.getRefData().getCount() == 0 ? fCorpseClearDelay : std::min(fCorpseRespawnDelay, fCorpseClearDelay);
|
||||
|
||||
if (isFlagBitSet(ptr, ESM::Creature::Respawn)
|
||||
&& creatureStats.getTimeOfDeath() + delay <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
||||
{
|
||||
if (ptr.getCellRef().hasContentFile())
|
||||
{
|
||||
|
|
|
@ -44,7 +44,28 @@ namespace MWClass
|
|||
ensureCustomData(ptr);
|
||||
|
||||
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
||||
customData.mSpawn = true;
|
||||
if (customData.mSpawn)
|
||||
return;
|
||||
|
||||
MWWorld::Ptr creature = (customData.mSpawnActorId == -1) ? MWWorld::Ptr() : MWBase::Environment::get().getWorld()->searchPtrViaActorId(customData.mSpawnActorId);
|
||||
if (!creature.isEmpty())
|
||||
{
|
||||
const MWMechanics::CreatureStats& creatureStats = creature.getClass().getCreatureStats(creature);
|
||||
if (creature.getRefData().getCount() == 0)
|
||||
customData.mSpawn = true;
|
||||
else if (creatureStats.isDead())
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
||||
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||
|
||||
float delay = std::min(fCorpseRespawnDelay, fCorpseClearDelay);
|
||||
if (creatureStats.getTimeOfDeath() + delay <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
||||
customData.mSpawn = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
customData.mSpawn = true;
|
||||
}
|
||||
|
||||
void CreatureLevList::registerSelf()
|
||||
|
|
|
@ -1292,7 +1292,18 @@ namespace MWClass
|
|||
|
||||
void Npc::respawn(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
if (ptr.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Respawn)
|
||||
const MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
|
||||
if (ptr.getRefData().getCount() > 0 && !creatureStats.isDead())
|
||||
return;
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
|
||||
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
|
||||
|
||||
float delay = ptr.getRefData().getCount() == 0 ? fCorpseClearDelay : std::min(fCorpseRespawnDelay, fCorpseClearDelay);
|
||||
|
||||
if (ptr.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Respawn
|
||||
&& creatureStats.getTimeOfDeath() + delay <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
||||
{
|
||||
if (ptr.getCellRef().hasContentFile())
|
||||
{
|
||||
|
|
|
@ -187,6 +187,9 @@ namespace MWMechanics
|
|||
|
||||
if (index==0 && mDynamic[index].getCurrent()<1)
|
||||
{
|
||||
if (!mDead)
|
||||
mTimeOfDeath = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
|
||||
mDead = true;
|
||||
|
||||
mDynamic[index].setModifier(0);
|
||||
|
@ -503,6 +506,7 @@ namespace MWMechanics
|
|||
state.mLevel = mLevel;
|
||||
state.mActorId = mActorId;
|
||||
state.mDeathAnimation = mDeathAnimation;
|
||||
state.mTimeOfDeath = mTimeOfDeath.toEsm();
|
||||
|
||||
mSpells.writeState(state.mSpells);
|
||||
mActiveSpells.writeState(state.mActiveSpells);
|
||||
|
@ -549,6 +553,7 @@ namespace MWMechanics
|
|||
mLevel = state.mLevel;
|
||||
mActorId = state.mActorId;
|
||||
mDeathAnimation = state.mDeathAnimation;
|
||||
mTimeOfDeath = MWWorld::TimeStamp(state.mTimeOfDeath);
|
||||
|
||||
mSpells.readState(state.mSpells);
|
||||
mActiveSpells.readState(state.mActiveSpells);
|
||||
|
@ -622,6 +627,11 @@ namespace MWMechanics
|
|||
mDeathAnimation = index;
|
||||
}
|
||||
|
||||
MWWorld::TimeStamp CreatureStats::getTimeOfDeath() const
|
||||
{
|
||||
return mTimeOfDeath;
|
||||
}
|
||||
|
||||
std::map<CreatureStats::SummonKey, int>& CreatureStats::getSummonedCreatureMap()
|
||||
{
|
||||
return mSummonedCreatures;
|
||||
|
|
|
@ -65,6 +65,8 @@ namespace MWMechanics
|
|||
// The index of the death animation that was played
|
||||
unsigned char mDeathAnimation;
|
||||
|
||||
MWWorld::TimeStamp mTimeOfDeath;
|
||||
|
||||
public:
|
||||
typedef std::pair<int, std::string> SummonKey; // <ESM::MagicEffect index, spell ID>
|
||||
private:
|
||||
|
@ -259,6 +261,8 @@ namespace MWMechanics
|
|||
unsigned char getDeathAnimation() const;
|
||||
void setDeathAnimation(unsigned char index);
|
||||
|
||||
MWWorld::TimeStamp getTimeOfDeath() const;
|
||||
|
||||
int getActorId();
|
||||
///< Will generate an actor ID, if the actor does not have one yet.
|
||||
|
||||
|
|
|
@ -493,7 +493,8 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
// but some mods may be using it as a reload detector.
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
|
||||
|
||||
// Do not trigger erroneous cellChanged events
|
||||
// Since we passed "changeEvent=false" to changeCell, we shouldn't have triggered the cell change flag.
|
||||
// But make sure the flag is cleared anyway in case it was set from an earlier game.
|
||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
|
|
@ -902,21 +902,22 @@ namespace MWWorld
|
|||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::Creature>::List::iterator it (mCreatures.mList.begin()); it!=mCreatures.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::NPC>::List::iterator it (mNpcs.mList.begin()); it!=mNpcs.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::CreatureLevList>::List::iterator it (mCreatureLists.mList.begin()); it!=mCreatureLists.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (CellRefList<ESM::Creature>::List::iterator it (mCreatures.mList.begin()); it!=mCreatures.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::NPC>::List::iterator it (mNpcs.mList.begin()); it!=mNpcs.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
for (CellRefList<ESM::CreatureLevList>::List::iterator it (mCreatureLists.mList.begin()); it!=mCreatureLists.mList.end(); ++it)
|
||||
{
|
||||
Ptr ptr (&*it, this);
|
||||
ptr.getClass().respawn(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace MWWorld
|
|||
mActiveCells.erase(*iter);
|
||||
}
|
||||
|
||||
void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener)
|
||||
void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn)
|
||||
{
|
||||
std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell);
|
||||
|
||||
|
@ -270,12 +270,13 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
cell->respawn();
|
||||
|
||||
// register local scripts
|
||||
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
||||
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
|
||||
|
||||
if (respawn)
|
||||
cell->respawn();
|
||||
|
||||
// ... then references. This is important for adjustPosition to work correctly.
|
||||
/// \todo rescale depending on the state of a new GMST
|
||||
insertCell (*cell, true, loadingListener);
|
||||
|
@ -329,7 +330,7 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
void Scene::changeCellGrid (int X, int Y)
|
||||
void Scene::changeCellGrid (int X, int Y, bool changeEvent)
|
||||
{
|
||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
Loading::ScopedLoad load(loadingListener);
|
||||
|
@ -403,7 +404,7 @@ namespace MWWorld
|
|||
{
|
||||
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
||||
|
||||
loadCell (cell, loadingListener);
|
||||
loadCell (cell, loadingListener, changeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +412,8 @@ namespace MWWorld
|
|||
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(X,Y);
|
||||
MWBase::Environment::get().getWindowManager()->changeCell(current);
|
||||
|
||||
mCellChanged = true;
|
||||
if (changeEvent)
|
||||
mCellChanged = true;
|
||||
|
||||
mPreloader->updateCache(mRendering.getReferenceTime());
|
||||
}
|
||||
|
@ -484,7 +486,7 @@ namespace MWWorld
|
|||
return mActiveCells;
|
||||
}
|
||||
|
||||
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
||||
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool changeEvent)
|
||||
{
|
||||
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
|
||||
bool loadcell = (mCurrentCell == NULL);
|
||||
|
@ -530,7 +532,7 @@ namespace MWWorld
|
|||
loadingListener->setProgressRange(refsToLoad);
|
||||
|
||||
// Load cell.
|
||||
loadCell (cell, loadingListener);
|
||||
loadCell (cell, loadingListener, changeEvent);
|
||||
|
||||
changePlayerCell(cell, position, true);
|
||||
|
||||
|
@ -540,21 +542,24 @@ namespace MWWorld
|
|||
// Sky system
|
||||
MWBase::Environment::get().getWorld()->adjustSky();
|
||||
|
||||
mCellChanged = true; MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||
if (changeEvent)
|
||||
mCellChanged = true;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
||||
|
||||
mPreloader->updateCache(mRendering.getReferenceTime());
|
||||
}
|
||||
|
||||
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)
|
||||
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
MWBase::Environment::get().getWorld()->positionToIndex (position.pos[0], position.pos[1], x, y);
|
||||
|
||||
changeCellGrid(x, y);
|
||||
changeCellGrid(x, y, changeEvent);
|
||||
|
||||
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
||||
changePlayerCell(current, position, adjustPlayerPos);
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace MWWorld
|
|||
void insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener);
|
||||
|
||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||
void changeCellGrid (int X, int Y);
|
||||
void changeCellGrid (int X, int Y, bool changeEvent = true);
|
||||
|
||||
void getGridCenter(int& cellX, int& cellY);
|
||||
|
||||
|
@ -90,7 +90,7 @@ namespace MWWorld
|
|||
|
||||
void unloadCell (CellStoreCollection::iterator iter);
|
||||
|
||||
void loadCell (CellStore *cell, Loading::Listener* loadingListener);
|
||||
void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn);
|
||||
|
||||
void playerMoved (const osg::Vec3f& pos);
|
||||
|
||||
|
@ -103,11 +103,13 @@ namespace MWWorld
|
|||
bool hasCellChanged() const;
|
||||
///< Has the set of active cells changed, since the last frame?
|
||||
|
||||
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position);
|
||||
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool changeEvent=true);
|
||||
///< Move to interior cell.
|
||||
/// @param changeEvent Set cellChanged flag?
|
||||
|
||||
void changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos);
|
||||
void changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent=true);
|
||||
///< Move to exterior cell.
|
||||
/// @param changeEvent Set cellChanged flag?
|
||||
|
||||
void changeToVoid();
|
||||
///< Change into a void
|
||||
|
|
|
@ -962,11 +962,11 @@ namespace MWWorld
|
|||
return mTimeScale->getFloat();
|
||||
}
|
||||
|
||||
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
||||
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool changeEvent)
|
||||
{
|
||||
mPhysics->clearQueuedMovement();
|
||||
|
||||
if (mCurrentWorldSpace != cellName)
|
||||
if (changeEvent && mCurrentWorldSpace != cellName)
|
||||
{
|
||||
// changed worldspace
|
||||
mProjectileManager->clear();
|
||||
|
@ -976,34 +976,34 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
removeContainerScripts(getPlayerPtr());
|
||||
mWorldScene->changeToInteriorCell(cellName, position);
|
||||
mWorldScene->changeToInteriorCell(cellName, position, changeEvent);
|
||||
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
|
||||
}
|
||||
|
||||
void World::changeToExteriorCell (const ESM::Position& position)
|
||||
void World::changeToExteriorCell (const ESM::Position& position, bool changeEvent)
|
||||
{
|
||||
mPhysics->clearQueuedMovement();
|
||||
|
||||
if (mCurrentWorldSpace != "sys::default") // FIXME
|
||||
if (changeEvent && mCurrentWorldSpace != "sys::default") // FIXME
|
||||
{
|
||||
// changed worldspace
|
||||
mProjectileManager->clear();
|
||||
mRendering->notifyWorldSpaceChanged();
|
||||
}
|
||||
removeContainerScripts(getPlayerPtr());
|
||||
mWorldScene->changeToExteriorCell(position, true);
|
||||
mWorldScene->changeToExteriorCell(position, true, changeEvent);
|
||||
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
|
||||
}
|
||||
|
||||
void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange)
|
||||
void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool changeEvent)
|
||||
{
|
||||
if (!detectWorldSpaceChange)
|
||||
if (!changeEvent)
|
||||
mCurrentWorldSpace = cellId.mWorldspace;
|
||||
|
||||
if (cellId.mPaged)
|
||||
changeToExteriorCell (position);
|
||||
changeToExteriorCell (position, changeEvent);
|
||||
else
|
||||
changeToInteriorCell (cellId.mWorldspace, position);
|
||||
changeToInteriorCell (cellId.mWorldspace, position, changeEvent);
|
||||
}
|
||||
|
||||
void World::markCellAsUnchanged()
|
||||
|
|
|
@ -324,15 +324,16 @@ namespace MWWorld
|
|||
|
||||
virtual float getTimeScaleFactor() const;
|
||||
|
||||
virtual void changeToInteriorCell (const std::string& cellName,
|
||||
const ESM::Position& position);
|
||||
virtual void changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool changeEvent = true);
|
||||
///< Move to interior cell.
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual void changeToExteriorCell (const ESM::Position& position);
|
||||
virtual void changeToExteriorCell (const ESM::Position& position, bool changeEvent = true);
|
||||
///< Move to exterior cell.
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true);
|
||||
///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool changeEvent=true);
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
|
|
@ -87,6 +87,8 @@ void ESM::CreatureStats::load (ESMReader &esm)
|
|||
mDeathAnimation = 0;
|
||||
esm.getHNOT (mDeathAnimation, "DANM");
|
||||
|
||||
esm.getHNOT (mTimeOfDeath, "DTIM");
|
||||
|
||||
mSpells.load(esm);
|
||||
mActiveSpells.load(esm);
|
||||
mAiSequence.load(esm);
|
||||
|
@ -193,6 +195,9 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
|
|||
if (mDeathAnimation)
|
||||
esm.writeHNT ("DANM", mDeathAnimation);
|
||||
|
||||
if (mTimeOfDeath.mHour != 0 && mTimeOfDeath.mDay != 0)
|
||||
esm.writeHNT ("DTIM", mTimeOfDeath);
|
||||
|
||||
mSpells.save(esm);
|
||||
mActiveSpells.save(esm);
|
||||
mAiSequence.save(esm);
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace ESM
|
|||
bool mRecalcDynamicStats;
|
||||
int mDrawState;
|
||||
unsigned char mDeathAnimation;
|
||||
ESM::TimeStamp mTimeOfDeath;
|
||||
|
||||
int mLevel;
|
||||
|
||||
|
|
Loading…
Reference in a new issue