2010-08-03 15:24:44 +02:00
|
|
|
#include "creaturelevlist.hpp"
|
|
|
|
|
2022-01-22 15:58:41 +01:00
|
|
|
#include <components/esm3/creaturelevliststate.hpp>
|
|
|
|
#include <components/esm3/loadlevlist.hpp>
|
2010-08-03 15:24:44 +02:00
|
|
|
|
2014-01-18 07:26:27 +01:00
|
|
|
#include "../mwmechanics/levelledlist.hpp"
|
|
|
|
|
2021-10-17 17:44:07 +04:00
|
|
|
#include "../mwworld/cellstore.hpp"
|
2014-01-18 07:26:27 +01:00
|
|
|
#include "../mwworld/customdata.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
|
|
|
#include "../mwworld/manualref.hpp"
|
|
|
|
|
2016-02-09 03:06:00 +01:00
|
|
|
#include "../mwmechanics/creaturestats.hpp"
|
2014-01-18 07:26:27 +01:00
|
|
|
|
2022-06-26 16:42:29 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
|
2015-11-29 14:13:14 +01:00
|
|
|
namespace MWClass
|
2014-01-18 07:26:27 +01:00
|
|
|
{
|
2021-04-03 12:59:44 +02:00
|
|
|
class CreatureLevListCustomData : public MWWorld::TypedCustomData<CreatureLevListCustomData>
|
2014-01-18 07:26:27 +01:00
|
|
|
{
|
2015-11-29 14:13:14 +01:00
|
|
|
public:
|
2014-05-15 00:23:53 +02:00
|
|
|
// actorId of the creature we spawned
|
|
|
|
int mSpawnActorId;
|
2014-05-17 09:05:41 +02:00
|
|
|
bool mSpawn; // Should a new creature be spawned?
|
2014-05-15 00:23:53 +02:00
|
|
|
|
2020-10-16 22:18:54 +04:00
|
|
|
CreatureLevListCustomData& asCreatureLevListCustomData() override { return *this; }
|
|
|
|
const CreatureLevListCustomData& asCreatureLevListCustomData() const override { return *this; }
|
2014-01-18 07:26:27 +01:00
|
|
|
};
|
|
|
|
|
2022-04-04 02:44:53 +02:00
|
|
|
CreatureLevList::CreatureLevList()
|
|
|
|
: MWWorld::RegisteredClass<CreatureLevList>(ESM::CreatureLevList::sRecordId)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:44:07 +04:00
|
|
|
MWWorld::Ptr CreatureLevList::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
|
|
|
|
{
|
|
|
|
const MWWorld::LiveCellRef<ESM::CreatureLevList>* ref = ptr.get<ESM::CreatureLevList>();
|
|
|
|
|
|
|
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreatureLevList::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
|
|
|
|
{
|
|
|
|
if (ptr.getRefData().getCustomData() == nullptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
|
|
|
MWWorld::Ptr creature = (customData.mSpawnActorId == -1)
|
|
|
|
? MWWorld::Ptr()
|
|
|
|
: MWBase::Environment::get().getWorld()->searchPtrViaActorId(customData.mSpawnActorId);
|
|
|
|
if (!creature.isEmpty())
|
|
|
|
MWBase::Environment::get().getWorld()->adjustPosition(creature, force);
|
|
|
|
}
|
|
|
|
|
2022-08-16 21:15:03 +02:00
|
|
|
std::string_view CreatureLevList::getName(const MWWorld::ConstPtr& ptr) const
|
2010-08-03 17:11:41 +02:00
|
|
|
{
|
2022-08-16 21:15:03 +02:00
|
|
|
return {};
|
2010-08-03 17:11:41 +02:00
|
|
|
}
|
|
|
|
|
2019-09-10 21:56:10 +03:00
|
|
|
bool CreatureLevList::hasToolTip(const MWWorld::ConstPtr& ptr) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-05-17 09:05:41 +02:00
|
|
|
void CreatureLevList::respawn(const MWWorld::Ptr& ptr) const
|
|
|
|
{
|
|
|
|
ensureCustomData(ptr);
|
|
|
|
|
2015-11-29 14:13:14 +01:00
|
|
|
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
2016-02-27 12:53:07 +01:00
|
|
|
if (customData.mSpawn)
|
|
|
|
return;
|
|
|
|
|
2021-12-06 13:46:56 +00:00
|
|
|
MWWorld::Ptr creature;
|
|
|
|
if (customData.mSpawnActorId != -1)
|
|
|
|
{
|
|
|
|
creature = MWBase::Environment::get().getWorld()->searchPtrViaActorId(customData.mSpawnActorId);
|
|
|
|
if (creature.isEmpty())
|
|
|
|
creature = ptr.getCell()->getMovedActor(customData.mSpawnActorId);
|
|
|
|
}
|
2016-02-27 12:53:07 +01:00
|
|
|
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
|
2023-04-20 21:07:53 +02:00
|
|
|
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
2018-08-29 18:38:12 +03:00
|
|
|
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->mValue.getFloat();
|
|
|
|
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->mValue.getFloat();
|
2016-02-27 12:53:07 +01:00
|
|
|
|
|
|
|
float delay = std::min(fCorpseRespawnDelay, fCorpseClearDelay);
|
|
|
|
if (creatureStats.getTimeOfDeath() + delay <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
|
|
|
customData.mSpawn = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
customData.mSpawn = true;
|
2014-05-17 09:05:41 +02:00
|
|
|
}
|
|
|
|
|
2016-02-09 03:06:00 +01:00
|
|
|
void CreatureLevList::getModelsToPreload(const MWWorld::Ptr& ptr, std::vector<std::string>& models) const
|
|
|
|
{
|
2016-02-22 14:31:02 +01:00
|
|
|
// disable for now, too many false positives
|
|
|
|
/*
|
2016-02-09 03:06:00 +01:00
|
|
|
const MWWorld::LiveCellRef<ESM::CreatureLevList> *ref = ptr.get<ESM::CreatureLevList>();
|
|
|
|
for (std::vector<ESM::LevelledListBase::LevelItem>::const_iterator it = ref->mBase->mList.begin(); it !=
|
|
|
|
ref->mBase->mList.end(); ++it)
|
|
|
|
{
|
|
|
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
if (it->mLevel > player.getClass().getCreatureStats(player).getLevel())
|
|
|
|
continue;
|
|
|
|
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2016-02-09 03:06:00 +01:00
|
|
|
MWWorld::ManualRef ref(store, it->mId);
|
|
|
|
ref.getPtr().getClass().getModelsToPreload(ref.getPtr(), models);
|
|
|
|
}
|
2016-02-22 14:31:02 +01:00
|
|
|
*/
|
2016-02-09 03:06:00 +01:00
|
|
|
}
|
|
|
|
|
2015-02-11 12:10:46 +01:00
|
|
|
void CreatureLevList::insertObjectRendering(
|
|
|
|
const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
|
2014-01-18 07:26:27 +01:00
|
|
|
{
|
|
|
|
ensureCustomData(ptr);
|
2014-05-15 00:23:53 +02:00
|
|
|
|
2015-11-29 14:13:14 +01:00
|
|
|
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
2014-05-17 09:05:41 +02:00
|
|
|
if (!customData.mSpawn)
|
|
|
|
return;
|
2014-05-15 00:23:53 +02:00
|
|
|
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
2022-03-06 21:56:02 +02:00
|
|
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
2023-01-04 22:18:56 +01:00
|
|
|
const ESM::RefId& id = MWMechanics::getLevelledItem(
|
|
|
|
store.get<ESM::CreatureLevList>().find(ptr.getCellRef().getRefId()), true, prng);
|
2014-05-15 00:23:53 +02:00
|
|
|
|
|
|
|
if (!id.empty())
|
|
|
|
{
|
2014-05-17 09:05:41 +02:00
|
|
|
// Delete the previous creature
|
|
|
|
if (customData.mSpawnActorId != -1)
|
|
|
|
{
|
|
|
|
MWWorld::Ptr creature
|
|
|
|
= MWBase::Environment::get().getWorld()->searchPtrViaActorId(customData.mSpawnActorId);
|
|
|
|
if (!creature.isEmpty())
|
|
|
|
MWBase::Environment::get().getWorld()->deleteObject(creature);
|
|
|
|
customData.mSpawnActorId = -1;
|
|
|
|
}
|
|
|
|
|
2016-10-31 00:23:51 +09:00
|
|
|
MWWorld::ManualRef manualRef(store, id);
|
|
|
|
manualRef.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition());
|
2020-04-12 13:14:32 +03:00
|
|
|
manualRef.getPtr().getCellRef().setScale(ptr.getCellRef().getScale());
|
2016-10-31 00:23:51 +09:00
|
|
|
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(
|
|
|
|
manualRef.getPtr(), ptr.getCell(), ptr.getCellRef().getPosition());
|
2014-05-15 00:23:53 +02:00
|
|
|
customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId();
|
2014-05-17 09:05:41 +02:00
|
|
|
customData.mSpawn = false;
|
2014-05-15 00:23:53 +02:00
|
|
|
}
|
2014-09-18 06:06:20 +02:00
|
|
|
else
|
|
|
|
customData.mSpawn = false;
|
2014-01-18 07:26:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CreatureLevList::ensureCustomData(const MWWorld::Ptr& ptr) const
|
|
|
|
{
|
|
|
|
if (!ptr.getRefData().getCustomData())
|
|
|
|
{
|
2021-04-03 00:48:35 +02:00
|
|
|
std::unique_ptr<CreatureLevListCustomData> data = std::make_unique<CreatureLevListCustomData>();
|
2014-05-15 00:23:53 +02:00
|
|
|
data->mSpawnActorId = -1;
|
2014-05-17 09:05:41 +02:00
|
|
|
data->mSpawn = true;
|
2014-01-18 07:26:27 +01:00
|
|
|
|
2021-04-03 00:48:35 +02:00
|
|
|
ptr.getRefData().setCustomData(std::move(data));
|
2014-05-15 00:23:53 +02:00
|
|
|
}
|
|
|
|
}
|
2014-01-18 07:26:27 +01:00
|
|
|
|
2014-05-15 00:23:53 +02:00
|
|
|
void CreatureLevList::readAdditionalState(const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
|
|
|
|
{
|
2015-12-18 00:07:13 +01:00
|
|
|
if (!state.mHasCustomState)
|
|
|
|
return;
|
|
|
|
|
2014-05-15 00:23:53 +02:00
|
|
|
ensureCustomData(ptr);
|
2015-11-29 14:13:14 +01:00
|
|
|
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
2020-03-17 14:15:19 +04:00
|
|
|
const ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
|
|
|
customData.mSpawnActorId = levListState.mSpawnActorId;
|
|
|
|
customData.mSpawn = levListState.mSpawn;
|
2014-05-15 00:23:53 +02:00
|
|
|
}
|
2014-01-18 07:26:27 +01:00
|
|
|
|
2015-12-18 00:18:06 +01:00
|
|
|
void CreatureLevList::writeAdditionalState(const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const
|
2014-05-15 00:23:53 +02:00
|
|
|
{
|
2015-12-18 00:07:13 +01:00
|
|
|
if (!ptr.getRefData().getCustomData())
|
|
|
|
{
|
|
|
|
state.mHasCustomState = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-19 16:19:52 +01:00
|
|
|
const CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
|
2020-03-17 14:15:19 +04:00
|
|
|
ESM::CreatureLevListState& levListState = state.asCreatureLevListState();
|
|
|
|
levListState.mSpawnActorId = customData.mSpawnActorId;
|
|
|
|
levListState.mSpawn = customData.mSpawn;
|
2014-01-18 07:26:27 +01:00
|
|
|
}
|
2010-08-03 15:24:44 +02:00
|
|
|
}
|