You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/apps/openmw/mwclass/creaturelevlist.cpp

182 lines
6.7 KiB
C++

#include "creaturelevlist.hpp"
#include <components/esm/loadlevlist.hpp>
#include <components/esm/creaturelevliststate.hpp>
#include "../mwmechanics/levelledlist.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwmechanics/creaturestats.hpp"
namespace MWClass
{
class CreatureLevListCustomData : public MWWorld::CustomData
{
public:
// actorId of the creature we spawned
int mSpawnActorId;
bool mSpawn; // Should a new creature be spawned?
virtual MWWorld::CustomData *clone() const;
virtual CreatureLevListCustomData& asCreatureLevListCustomData()
{
return *this;
}
virtual const CreatureLevListCustomData& asCreatureLevListCustomData() const
{
return *this;
}
};
MWWorld::CustomData *CreatureLevListCustomData::clone() const
{
return new CreatureLevListCustomData (*this);
}
std::string CreatureLevList::getName (const MWWorld::ConstPtr& ptr) const
{
return "";
}
void CreatureLevList::respawn(const MWWorld::Ptr &ptr) const
{
ensureCustomData(ptr);
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
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()
{
std::shared_ptr<Class> instance (new CreatureLevList);
registerClass (typeid (ESM::CreatureLevList).name(), instance);
}
void CreatureLevList::getModelsToPreload(const MWWorld::Ptr &ptr, std::vector<std::string> &models) const
{
// disable for now, too many false positives
/*
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;
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
MWWorld::ManualRef ref(store, it->mId);
ref.getPtr().getClass().getModelsToPreload(ref.getPtr(), models);
}
*/
}
void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, const std::string& model, MWRender::RenderingInterface &renderingInterface) const
{
ensureCustomData(ptr);
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
if (!customData.mSpawn)
return;
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
ptr.get<ESM::CreatureLevList>();
std::string id = MWMechanics::getLevelledItem(ref->mBase, true);
if (!id.empty())
{
// 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;
}
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
MWWorld::ManualRef manualRef(store, id);
manualRef.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition());
/*
Start of tes3mp change (major)
Don't spawn leveled creatures in multiplayer; they'll be spawned when the server requests them
*/
//MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(manualRef.getPtr(), ptr.getCell() , ptr.getCellRef().getPosition());
//customData.mSpawnActorId = placed.getClass().getCreatureStats(placed).getActorId();
/*
End of tes3mp change (major)
*/
customData.mSpawn = false;
}
else
customData.mSpawn = false;
}
void CreatureLevList::ensureCustomData(const MWWorld::Ptr &ptr) const
{
if (!ptr.getRefData().getCustomData())
{
std::unique_ptr<CreatureLevListCustomData> data (new CreatureLevListCustomData);
data->mSpawnActorId = -1;
data->mSpawn = true;
ptr.getRefData().setCustomData(data.release());
}
}
void CreatureLevList::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const
{
if (!state.mHasCustomState)
return;
const ESM::CreatureLevListState& state2 = dynamic_cast<const ESM::CreatureLevListState&> (state);
ensureCustomData(ptr);
CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
customData.mSpawnActorId = state2.mSpawnActorId;
customData.mSpawn = state2.mSpawn;
}
void CreatureLevList::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state)
const
{
ESM::CreatureLevListState& state2 = dynamic_cast<ESM::CreatureLevListState&> (state);
if (!ptr.getRefData().getCustomData())
{
state.mHasCustomState = false;
return;
}
const CreatureLevListCustomData& customData = ptr.getRefData().getCustomData()->asCreatureLevListCustomData();
state2.mSpawnActorId = customData.mSpawnActorId;
state2.mSpawn = customData.mSpawn;
}
}