[General] Implement ActorAI packet, part 3

The server can now cancel actor AI, make actors travel to a location, make actors wander, and make actors get escorted by a player or another actor.
0.6.3
David Cernat 7 years ago
parent 5baef09f79
commit 0e13207afe

@ -327,6 +327,23 @@ void ActorFunctions::SetActorAITargetToActor(int refNumIndex, int mpNum) noexcep
tempActor.aiTarget.mpNum = mpNum; tempActor.aiTarget.mpNum = mpNum;
} }
void ActorFunctions::SetActorAICoordinates(double x, double y, double z) noexcept
{
tempActor.aiCoordinates.pos[0] = x;
tempActor.aiCoordinates.pos[1] = y;
tempActor.aiCoordinates.pos[2] = z;
}
void ActorFunctions::SetActorAIDistance(unsigned int distance) noexcept
{
tempActor.aiDistance = distance;
}
void ActorFunctions::SetActorAIDuration(unsigned int duration) noexcept
{
tempActor.aiDuration = duration;
}
void ActorFunctions::EquipActorItem(unsigned short slot, const char *refId, unsigned int count, int charge, double enchantmentCharge) noexcept void ActorFunctions::EquipActorItem(unsigned short slot, const char *refId, unsigned int count, int charge, double enchantmentCharge) noexcept
{ {
tempActor.equipmentItems[slot].refId = refId; tempActor.equipmentItems[slot].refId = refId;

@ -70,6 +70,9 @@
{"SetActorAIAction", ActorFunctions::SetActorAIAction},\ {"SetActorAIAction", ActorFunctions::SetActorAIAction},\
{"SetActorAITargetToPlayer", ActorFunctions::SetActorAITargetToPlayer},\ {"SetActorAITargetToPlayer", ActorFunctions::SetActorAITargetToPlayer},\
{"SetActorAITargetToActor", ActorFunctions::SetActorAITargetToActor},\ {"SetActorAITargetToActor", ActorFunctions::SetActorAITargetToActor},\
{"SetActorAICoordinates", ActorFunctions::SetActorAICoordinates},\
{"SetActorAIDistance", ActorFunctions::SetActorAIDistance},\
{"SetActorAIDuration", ActorFunctions::SetActorAIDuration},\
\ \
{"EquipActorItem", ActorFunctions::EquipActorItem},\ {"EquipActorItem", ActorFunctions::EquipActorItem},\
{"UnequipActorItem", ActorFunctions::UnequipActorItem},\ {"UnequipActorItem", ActorFunctions::UnequipActorItem},\
@ -566,6 +569,32 @@ public:
*/ */
static void SetActorAITargetToActor(int refNumIndex, int mpNum) noexcept; static void SetActorAITargetToActor(int refNumIndex, int mpNum) noexcept;
/**
* \brief Set the coordinates for the AI package associated with the current AI action.
*
* \param x The X coordinate.
* \param y The Y coordinate.
* \param z The Z coordinate.
* \return void
*/
static void SetActorAICoordinates(double x, double y, double z) noexcept;
/**
* \brief Set the distance of the AI package associated with the current AI action.
*
* \param duration The distance of the package.
* \return void
*/
static void SetActorAIDistance(unsigned int distance) noexcept;
/**
* \brief Set the duration of the AI package associated with the current AI action.
*
* \param duration The duration of the package.
* \return void
*/
static void SetActorAIDuration(unsigned int duration) noexcept;
/** /**
* \brief Equip an item in a certain slot of the equipment of the temporary actor stored * \brief Equip an item in a certain slot of the equipment of the temporary actor stored
* on the server. * on the server.

@ -1,7 +1,3 @@
//
// Created by koncord on 02.03.16.
//
#include "Items.hpp" #include "Items.hpp"
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>

@ -257,6 +257,9 @@ void Cell::readAI(ActorList& actorList)
{ {
DedicatedActor *actor = dedicatedActors[mapIndex]; DedicatedActor *actor = dedicatedActors[mapIndex];
actor->aiAction = baseActor.aiAction; actor->aiAction = baseActor.aiAction;
actor->aiDistance = baseActor.aiDistance;
actor->aiDuration = baseActor.aiDuration;
actor->aiCoordinates = baseActor.aiCoordinates;
actor->hasAiTarget = baseActor.hasAiTarget; actor->hasAiTarget = baseActor.hasAiTarget;
actor->aiTarget = baseActor.aiTarget; actor->aiTarget = baseActor.aiTarget;
actor->setAI(); actor->setAI();

@ -7,7 +7,11 @@
#include "../mwdialogue/dialoguemanagerimp.hpp" #include "../mwdialogue/dialoguemanagerimp.hpp"
#include "../mwmechanics/aicombat.hpp" #include "../mwmechanics/aicombat.hpp"
#include "../mwmechanics/aiescort.hpp"
#include "../mwmechanics/aifollow.hpp" #include "../mwmechanics/aifollow.hpp"
#include "../mwmechanics/aitravel.hpp"
#include "../mwmechanics/aiwander.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanagerimp.hpp" #include "../mwmechanics/mechanicsmanagerimp.hpp"
#include "../mwmechanics/movement.hpp" #include "../mwmechanics/movement.hpp"
@ -207,7 +211,31 @@ void DedicatedActor::setEquipment()
void DedicatedActor::setAI() void DedicatedActor::setAI()
{ {
if (hasAiTarget) if (aiAction == mwmp::BaseActorList::CANCEL)
{
LOG_APPEND(Log::LOG_VERBOSE, "--- Cancelling AI sequence");
ptr.getClass().getCreatureStats(ptr).getAiSequence().clear();
}
else if (aiAction == mwmp::BaseActorList::TRAVEL)
{
LOG_APPEND(Log::LOG_VERBOSE, "--- Travelling to %f, %f, %f",
aiCoordinates.pos[0], aiCoordinates.pos[1], aiCoordinates.pos[2]);
MWMechanics::AiTravel package(aiCoordinates.pos[0], aiCoordinates.pos[1], aiCoordinates.pos[2]);
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true);
}
else if (aiAction == mwmp::BaseActorList::WANDER)
{
LOG_APPEND(Log::LOG_VERBOSE, "--- Wandering for distance %i and duration %i",
aiDistance, aiDuration);
std::vector<unsigned char> idleList;
MWMechanics::AiWander package(aiDistance, aiDuration, -1, idleList, true);
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true);
}
else if (hasAiTarget)
{ {
MWWorld::Ptr targetPtr; MWWorld::Ptr targetPtr;
@ -215,7 +243,9 @@ void DedicatedActor::setAI()
{ {
targetPtr = MechanicsHelper::getPlayerPtr(aiTarget); targetPtr = MechanicsHelper::getPlayerPtr(aiTarget);
LOG_APPEND(Log::LOG_VERBOSE, "-- DedicatedActor %s %i-%i has player target %s", targetPtr.getClass().getName(targetPtr).c_str()); LOG_APPEND(Log::LOG_VERBOSE, "-- DedicatedActor %s %i-%i has player target %s",
ptr.getCellRef().getRefId().c_str(), ptr.getCellRef().getRefNum().mIndex, ptr.getCellRef().getMpNum(),
targetPtr.getClass().getName(targetPtr).c_str());
} }
else else
{ {
@ -241,15 +271,28 @@ void DedicatedActor::setAI()
if (targetPtr) if (targetPtr)
{ {
if (aiAction == mwmp::BaseActorList::FOLLOW) if (aiAction == mwmp::BaseActorList::COMBAT)
{ {
MWMechanics::AiFollow package(targetPtr); LOG_APPEND(Log::LOG_VERBOSE, "--- Starting combat with target");
package.allowAnyDistance(true);
MWMechanics::AiCombat package(targetPtr);
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true); ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true);
} }
else if (aiAction == mwmp::BaseActorList::COMBAT) else if (aiAction == mwmp::BaseActorList::ESCORT)
{ {
MWMechanics::AiCombat package(targetPtr); LOG_APPEND(Log::LOG_VERBOSE, "--- Being escorted by target, for duration %i, to coordinates %f, %f, %f",
aiDuration, aiCoordinates.pos[0], aiCoordinates.pos[1], aiCoordinates.pos[2]);
MWMechanics::AiEscort package(targetPtr.getCellRef().getRefId(), aiDuration,
aiCoordinates.pos[0], aiCoordinates.pos[1], aiCoordinates.pos[2]);
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true);
}
else if (aiAction == mwmp::BaseActorList::FOLLOW)
{
LOG_APPEND(Log::LOG_VERBOSE, "--- Following target");
MWMechanics::AiFollow package(targetPtr);
package.allowAnyDistance(true);
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true); ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(package, ptr, true);
} }
} }

@ -44,6 +44,9 @@ namespace mwmp
bool hasAiTarget; bool hasAiTarget;
Target aiTarget; Target aiTarget;
unsigned int aiAction; unsigned int aiAction;
unsigned int aiDistance;
unsigned int aiDuration;
ESM::Position aiCoordinates;
bool hasPositionData; bool hasPositionData;
bool hasStatsDynamicData; bool hasStatsDynamicData;
@ -70,8 +73,12 @@ namespace mwmp
enum AI_ACTION enum AI_ACTION
{ {
FOLLOW = 0, CANCEL = 0,
COMBAT = 1 COMBAT = 1,
ESCORT = 2,
FOLLOW = 3,
TRAVEL = 4,
WANDER = 5
}; };
RakNet::RakNetGUID guid; RakNet::RakNetGUID guid;

@ -12,21 +12,38 @@ PacketActorAI::PacketActorAI(RakNet::RakPeerInterface *peer) : ActorPacket(peer)
void PacketActorAI::Actor(BaseActor &actor, bool send) void PacketActorAI::Actor(BaseActor &actor, bool send)
{ {
RW(actor.aiAction, send); RW(actor.aiAction, send);
RW(actor.hasAiTarget, send);
if (actor.hasAiTarget) if (actor.aiAction != mwmp::BaseActorList::CANCEL)
{ {
RW(actor.aiTarget.isPlayer, send); if (actor.aiAction == mwmp::BaseActorList::WANDER)
RW(actor.aiDistance, send);
if (actor.aiTarget.isPlayer) if (actor.aiAction == mwmp::BaseActorList::ESCORT || actor.aiAction == mwmp::BaseActorList::TRAVEL)
{ RW(actor.aiCoordinates, send);
RW(actor.aiTarget.guid, send);
} if (actor.aiAction == mwmp::BaseActorList::ESCORT || actor.aiAction == mwmp::BaseActorList::WANDER)
else RW(actor.aiDuration, send);
if (actor.aiAction == mwmp::BaseActorList::COMBAT || actor.aiAction == mwmp::BaseActorList::ESCORT ||
actor.aiAction == mwmp::BaseActorList::FOLLOW)
{ {
RW(actor.aiTarget.refId, send, true); RW(actor.hasAiTarget, send);
RW(actor.aiTarget.refNumIndex, send);
RW(actor.aiTarget.mpNum, send); if (actor.hasAiTarget)
{
RW(actor.aiTarget.isPlayer, send);
if (actor.aiTarget.isPlayer)
{
RW(actor.aiTarget.guid, send);
}
else
{
RW(actor.aiTarget.refId, send, true);
RW(actor.aiTarget.refNumIndex, send);
RW(actor.aiTarget.mpNum, send);
}
}
} }
} }
} }

Loading…
Cancel
Save