mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 07:09:39 +00:00
Fixes #1129: Change summoned creatures to use ActorId
Gracefully handles summoned creatures that are left behind in inactive cells.
This commit is contained in:
parent
99b4bc721b
commit
7697ab37e0
3 changed files with 44 additions and 15 deletions
|
@ -38,9 +38,12 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a
|
||||||
{
|
{
|
||||||
if (bound)
|
if (bound)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor);
|
if (actor.getClass().getContainerStore(actor).count(item) == 0)
|
||||||
MWWorld::ActionEquip action(newPtr);
|
{
|
||||||
action.execute(actor);
|
MWWorld::Ptr newPtr = *actor.getClass().getContainerStore(actor).add(item, 1, actor);
|
||||||
|
MWWorld::ActionEquip action(newPtr);
|
||||||
|
action.execute(actor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -534,28 +537,49 @@ namespace MWMechanics
|
||||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), creatureID, 1);
|
||||||
ref.getPtr().getCellRef().mPos = ipos;
|
ref.getPtr().getCellRef().mPos = ipos;
|
||||||
|
|
||||||
// TODO: Add AI to follow player and fight for him
|
MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr());
|
||||||
|
|
||||||
|
// Make the summoned creature follow its master and help in fights
|
||||||
AiFollow package(ptr.getRefData().getHandle());
|
AiFollow package(ptr.getRefData().getHandle());
|
||||||
MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr);
|
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr());
|
||||||
|
int creatureActorId = summonedCreatureStats.getActorId();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
|
||||||
|
|
||||||
// TODO: VFX_SummonStart, VFX_SummonEnd
|
// TODO: VFX_SummonStart, VFX_SummonEnd
|
||||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first, creatureActorId));
|
||||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string handle = creatureStats.mSummonedCreatures[it->first];
|
// Summon lifetime has expired. Try to delete the creature.
|
||||||
// TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation
|
int actorId = creatureStats.mSummonedCreatures[it->first];
|
||||||
// plays though, which is a rather lame exploit in vanilla.
|
creatureStats.mSummonedCreatures.erase(it->first);
|
||||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
|
|
||||||
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(actorId);
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty())
|
||||||
{
|
{
|
||||||
|
// TODO: Show death animation before deleting? We shouldn't allow looting the corpse while the animation
|
||||||
|
// plays though, which is a rather lame exploit in vanilla.
|
||||||
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
||||||
creatureStats.mSummonedCreatures.erase(it->first);
|
creatureStats.mSummonedCreatures.erase(it->first);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We didn't find the creature. It's probably in an inactive cell.
|
||||||
|
// Add to graveyard so we can delete it when the cell becomes active.
|
||||||
|
creatureStats.mSummonGraveyard.push_back(actorId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (std::vector<int>::iterator it = creatureStats.mSummonGraveyard.begin(); it != creatureStats.mSummonGraveyard.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it);
|
||||||
|
if (!ptr.isEmpty())
|
||||||
|
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr)
|
void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr)
|
||||||
|
|
|
@ -223,10 +223,16 @@ namespace MWMechanics
|
||||||
void setLastHitObject(const std::string &objectid);
|
void setLastHitObject(const std::string &objectid);
|
||||||
const std::string &getLastHitObject() const;
|
const std::string &getLastHitObject() const;
|
||||||
|
|
||||||
// Note, this is just a cache to avoid checking the whole container store every frame TODO: Put it somewhere else?
|
// Note, this is just a cache to avoid checking the whole container store every frame. We don't need to store it in saves.
|
||||||
|
// TODO: Put it somewhere else?
|
||||||
std::set<int> mBoundItems;
|
std::set<int> mBoundItems;
|
||||||
// Same as above
|
|
||||||
std::map<int, std::string> mSummonedCreatures;
|
// TODO: store in savegame
|
||||||
|
// TODO: encapsulate?
|
||||||
|
// <ESM::MagicEffect index, actor index>
|
||||||
|
std::map<int, int> mSummonedCreatures;
|
||||||
|
// Contains summoned creatures with an expired lifetime that have not been deleted yet.
|
||||||
|
std::vector<int> mSummonGraveyard;
|
||||||
|
|
||||||
void writeState (ESM::CreatureStats& state) const;
|
void writeState (ESM::CreatureStats& state) const;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace MWWorld
|
||||||
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
|
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
|
||||||
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
|
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
|
||||||
{
|
{
|
||||||
std::cout << "teleporting someone!" << (*it).getCellRef().mRefID;
|
|
||||||
executeImp(*it);
|
executeImp(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue