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/mwmechanics/aipursue.cpp

138 lines
4.2 KiB
C++

#include "aipursue.hpp"
#include <components/esm/aisequence.hpp>
#include <components/esm/loadmgef.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/action.hpp"
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include <components/openmw-mp/Log.hpp>
#include "../mwgui/windowmanagerimp.hpp"
#include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp"
/*
End of tes3mp addition
*/
#include "movement.hpp"
#include "creaturestats.hpp"
namespace MWMechanics
{
AiPursue::AiPursue(const MWWorld::Ptr& actor)
{
mTargetActorId = actor.getClass().getCreatureStats(actor).getActorId();
}
AiPursue::AiPursue(const ESM::AiSequence::AiPursue *pursue)
{
mTargetActorId = pursue->mTargetActorId;
}
AiPursue *MWMechanics::AiPursue::clone() const
{
return new AiPursue(*this);
}
bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
if(actor.getClass().getCreatureStats(actor).isDead())
return true;
const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId); //The target to follow
if(target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled() // Really we should be checking whether the target is currently registered
// with the MechanicsManager
)
return true; //Target doesn't exist
if (isTargetMagicallyHidden(target))
return true;
if(target.getClass().getCreatureStats(target).isDead())
return true;
/*
Start of tes3mp addition
Because multiplayer does not pause the game, prevent infinite arrest loops by ignoring
players already engaged in dialogue
Additionally, do not arrest players who are currently jailed
*/
if (target == MWBase::Environment::get().getWorld()->getPlayerPtr())
{
if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Dialogue) ||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Jail))
{
return true;
}
}
/*
End of tes3mp addition
*/
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
//Set the target desition from the actor
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
ESM::Position aPos = actor.getRefData().getPosition();
float pathTolerance = 100.0;
if (pathTo(actor, dest, duration, pathTolerance) &&
std::abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction
{
/*
Start of tes3mp addition
Record that the player has not died since the last attempt to arrest them
Close the player's inventory or open container and cancel any drag and drops
*/
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "After being pursued by %s, diedSinceArrestAttempt is now false", actor.getCellRef().getRefId().c_str());
mwmp::Main::get().getLocalPlayer()->diedSinceArrestAttempt = false;
mwmp::Main::get().getLocalPlayer()->closeInventoryWindows();
/*
End of tes3mp addition
*/
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
return true;
}
actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run
return false;
}
int AiPursue::getTypeId() const
{
return TypeIdPursue;
}
MWWorld::Ptr AiPursue::getTarget() const
{
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mTargetActorId);
}
void AiPursue::writeState(ESM::AiSequence::AiSequence &sequence) const
{
std::unique_ptr<ESM::AiSequence::AiPursue> pursue(new ESM::AiSequence::AiPursue());
pursue->mTargetActorId = mTargetActorId;
ESM::AiSequence::AiPackageContainer package;
package.mType = ESM::AiSequence::Ai_Pursue;
package.mPackage = pursue.release();
sequence.mPackages.push_back(package);
}
} // namespace MWMechanics