mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +00:00
[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.
This commit is contained in:
parent
5baef09f79
commit
0e13207afe
7 changed files with 136 additions and 24 deletions
|
@ -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);
|
||||||
|
|
||||||
|
if (actor.aiAction == mwmp::BaseActorList::ESCORT || actor.aiAction == mwmp::BaseActorList::WANDER)
|
||||||
|
RW(actor.aiDuration, send);
|
||||||
|
|
||||||
|
if (actor.aiAction == mwmp::BaseActorList::COMBAT || actor.aiAction == mwmp::BaseActorList::ESCORT ||
|
||||||
|
actor.aiAction == mwmp::BaseActorList::FOLLOW)
|
||||||
{
|
{
|
||||||
RW(actor.aiTarget.guid, send);
|
RW(actor.hasAiTarget, send);
|
||||||
}
|
|
||||||
else
|
if (actor.hasAiTarget)
|
||||||
{
|
{
|
||||||
RW(actor.aiTarget.refId, send, true);
|
RW(actor.aiTarget.isPlayer, send);
|
||||||
RW(actor.aiTarget.refNumIndex, send);
|
|
||||||
RW(actor.aiTarget.mpNum, 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…
Reference in a new issue