Skip to content

Commit

Permalink
EAI/Scripts/EscortAI: Enable specifying waypoint_path entry
Browse files Browse the repository at this point in the history
  • Loading branch information
killerwife committed May 28, 2022
1 parent 0d801e7 commit 63d9e7b
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 22 deletions.
2 changes: 1 addition & 1 deletion doc/EventAI.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ For all ACTION_T_RANDOM Actions, When a Particular Param is selected for the Eve
45 ACTION_T_THROW_AI_EVENT EventType, Radius, Target Throws an AIEvent of type (Param1) to nearby friendly Npcs in range of (Param2), Invoker of event is Target
46 ACTION_T_SET_THROW_MASK EventTypeMask Marks for which AIEvents the npc will throw AIEvents on its own.
47 ACTION_T_SET_STAND_STATE StandState Set the unit stand state (Param1) of the current creature.
48 ACTION_T_CHANGE_MOVEMENT MovementType, WanderDistance Change the unit movement type (Param1). If the movement type is Random Movement (1), the WanderDistance (Param2) must be provided. If the movement type is Waypoint Movement (2), Param2 is PathId. Param3 is asDefault.
48 ACTION_T_CHANGE_MOVEMENT MovementType, WanderDistance Change the unit movement type (Param1). If the movement type is Random Movement (1), the WanderDistance (Param2) must be provided. If the movement type is Waypoint Movement (2), Param2 is PathId. Param3 0x1 is asDefault, 0x2 forces waypoint, path or linear path movement to use waypoint_path table PathId
49 ACTION_T_REUSE
50 ACTION_T_SET_REACT_STATE ReactState Change react state of the creature
51 ACTION_T_PAUSE_WAYPOINTS DoPause Pause waypoints of creature
Expand Down
5 changes: 3 additions & 2 deletions doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,10 @@ Defining a buddy could be done in several way:
* datalog = movie id

20 SCRIPT_COMMAND_MOVEMENT resultingSource = Creature
* datalong = MovementType (0:idle, 1:random, 2:waypoint, 3:path)
* datalong = MovementType (0:idle, 1:random, 2:waypoint, 3:path, 4:linear)
* datalong2 = wanderDistance (for random movement), pathId (for waypoint movement)
* datalong3 = timer for timed random movement or pass target to waypoint and path movegen (by default, source targets self)
* datalong3 = 0x1 - timer for timed random movement or pass target to waypoint and path movegen (by default, source targets self)
* 0x2 - for waypoint, path and linear path - uses pathId from waypoint_path table
* data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL: RandomMovement around current position
* dataint = enum ForcedMovement

Expand Down
25 changes: 22 additions & 3 deletions src/game/AI/EventAI/CreatureEventAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ bool CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
case ACTION_T_CHANGE_MOVEMENT:
{
if (action.changeMovement.asDefault)
if (action.changeMovement.flags & CHANGE_MOVEMENT_FLAG_AS_DEFAULT)
m_defaultMovement = MovementGeneratorType(action.changeMovement.movementType);
switch (action.changeMovement.movementType)
{
Expand All @@ -1200,15 +1200,34 @@ bool CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
m_creature->GetMotionMaster()->MoveRandomAroundPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), float(action.changeMovement.wanderORpathID));
break;
case WAYPOINT_MOTION_TYPE:
{
m_creature->StopMoving();
m_creature->GetMotionMaster()->Clear(false, true);
m_creature->GetMotionMaster()->MoveWaypoint(action.changeMovement.wanderORpathID);
WaypointPathOrigin origin = PATH_NO_PATH;
if (action.changeMovement.flags & CHANGE_MOVEMENT_FLAG_WAYPOINT_PATH)
origin = PATH_FROM_WAYPOINT_PATH;
m_creature->GetMotionMaster()->MoveWaypoint(action.changeMovement.wanderORpathID, origin);
break;
}
case PATH_MOTION_TYPE:
{
m_creature->StopMoving();
WaypointPathOrigin origin = PATH_NO_PATH;
if (action.changeMovement.flags & CHANGE_MOVEMENT_FLAG_WAYPOINT_PATH)
origin = PATH_FROM_WAYPOINT_PATH;
m_creature->GetMotionMaster()->MovePath(action.changeMovement.wanderORpathID, origin);
break;
}
case LINEAR_WP_MOTION_TYPE:
{
m_creature->StopMoving();
m_creature->GetMotionMaster()->Clear(false, true);
m_creature->GetMotionMaster()->MoveLinearWP(action.changeMovement.wanderORpathID);
WaypointPathOrigin origin = PATH_NO_PATH;
if (action.changeMovement.flags & CHANGE_MOVEMENT_FLAG_WAYPOINT_PATH)
origin = PATH_FROM_WAYPOINT_PATH;
m_creature->GetMotionMaster()->MoveLinearWP(action.changeMovement.wanderORpathID, origin);
break;
}
}
break;
}
Expand Down
9 changes: 8 additions & 1 deletion src/game/AI/EventAI/CreatureEventAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ enum DespawnAggregation : uint32
AGGREGATION_DEATH = 0x4,
};

enum ChangeMovementFlags : uint32
{
CHANGE_MOVEMENT_FLAG_AS_DEFAULT = 0x1,
CHANGE_MOVEMENT_FLAG_WAYPOINT_PATH = 0x2,
CHANGE_MOVEMENT_MAX = 0x3,
};

struct CreatureEventAI_Action
{
EventAI_ActionType type: 16;
Expand Down Expand Up @@ -480,7 +487,7 @@ struct CreatureEventAI_Action
{
uint32 movementType;
uint32 wanderORpathID;
uint32 asDefault;
uint32 flags;
} changeMovement;
// ACTION_T_REUSE = 49
struct
Expand Down
6 changes: 3 additions & 3 deletions src/game/AI/EventAI/CreatureEventAIMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,10 +903,10 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
{
sLog.outErrorEventAI("Event %u Action %u uses invalid movement type %u (must be smaller than %u)", eventId, j + 1, action.changeMovement.movementType, MAX_DB_MOTION_TYPE);
}
if (action.changeMovement.asDefault > 1)
if (action.changeMovement.flags > CHANGE_MOVEMENT_MAX)
{
sLog.outErrorEventAI("Event %u Action %u uses invalid default movement setting %u. Setting to 0.", eventId, j + 1, action.changeMovement.asDefault);
action.changeMovement.asDefault = 0;
sLog.outErrorEventAI("Event %u Action %u uses invalid flags setting %u. Setting to 0.", eventId, j + 1, action.changeMovement.flags);
action.changeMovement.flags = 0;
}
break;
case ACTION_T_SET_REACT_STATE:
Expand Down
20 changes: 16 additions & 4 deletions src/game/AI/ScriptDevAI/base/escort_ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
m_isRunning(false),
m_canInstantRespawn(false),
m_canReturnToStart(false),
m_waypointPathID(0)
m_waypointPathID(0),
m_currentEscortWaypointPath(0)
{}

void npc_escortAI::GetAIInformation(ChatHandler& reader)
Expand Down Expand Up @@ -232,7 +233,7 @@ void npc_escortAI::SetRun(bool run)
}

// TODO: get rid of this many variables passed in function.
void npc_escortAI::Start(bool run, const Player* player, const Quest* quest, bool instantRespawn, bool canLoopPath)
void npc_escortAI::Start(bool run, const Player* player, const Quest* quest, bool instantRespawn, bool canLoopPath, uint32 waypointPath)
{
if (m_creature->GetVictim())
{
Expand All @@ -246,12 +247,23 @@ void npc_escortAI::Start(bool run, const Player* player, const Quest* quest, boo
return;
}

if (!sWaypointMgr.GetPathFromOrigin(m_creature->GetEntry(), m_creature->GetGUIDLow(), m_waypointPathID, PATH_FROM_EXTERNAL))
uint32 pathId = m_waypointPathID;
WaypointPathOrigin origin = PATH_FROM_EXTERNAL;
if (waypointPath)
{
pathId = waypointPath;
origin = PATH_FROM_WAYPOINT_PATH;
}

if (!sWaypointMgr.GetPathFromOrigin(m_creature->GetEntry(), m_creature->GetGUIDLow(), pathId, origin))
{
script_error_log("EscortAI attempt to start escorting for %s, but has no waypoints loaded.", m_creature->GetScriptName().data());
return;
}

if (origin == PATH_FROM_WAYPOINT_PATH)
m_currentEscortWaypointPath = pathId;

// set variables
m_isRunning = run;

Expand All @@ -276,7 +288,7 @@ void npc_escortAI::Start(bool run, const Player* player, const Quest* quest, boo

// Start moving along the path with 2500ms delay
m_creature->GetMotionMaster()->Clear(false, true);
m_creature->GetMotionMaster()->MoveWaypoint(m_waypointPathID, PATH_FROM_EXTERNAL, 2500);
m_creature->GetMotionMaster()->MoveWaypoint(pathId, origin, 2500);

JustStartedEscort();
}
Expand Down
5 changes: 4 additions & 1 deletion src/game/AI/ScriptDevAI/base/escort_ai.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct npc_escortAI : public ScriptedAI
virtual void WaypointReached(uint32 pointId) = 0;
virtual void WaypointStart(uint32 /*pointId*/) {}

void Start(bool run = false, const Player* player = nullptr, const Quest* quest = nullptr, bool instantRespawn = false, bool canLoopPath = false);
void Start(bool run = false, const Player* player = nullptr, const Quest* quest = nullptr, bool instantRespawn = false, bool canLoopPath = false, uint32 waypointPath = 0);

void SetRun(bool run = true);
void SetEscortPaused(bool paused);
Expand All @@ -52,6 +52,8 @@ struct npc_escortAI : public ScriptedAI
void FailQuestForPlayerAndGroup();

bool AssistPlayerInCombat(Unit* who) override;

uint32 GetCurrentWaypointPath() const { return m_currentEscortWaypointPath; }
protected:
Player* GetPlayerForEscort() const { return m_creature->GetMap()->GetPlayer(m_playerGuid); }
bool IsSD2EscortMovement(uint32 moveType) const;
Expand All @@ -75,6 +77,7 @@ struct npc_escortAI : public ScriptedAI
bool m_canReturnToStart; // if creature can walk same path (loop) without despawn. Not for regular escort quests.

uint32 m_waypointPathID;
uint32 m_currentEscortWaypointPath;
};

#endif
23 changes: 19 additions & 4 deletions src/game/DBScripts/ScriptMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2047,7 +2047,7 @@ bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTa

if (m_script->movement.movementType == WAYPOINT_MOTION_TYPE || m_script->movement.movementType == PATH_MOTION_TYPE)
{
if (m_script->movement.timerOrPassTarget && !pTarget)
if ((m_script->movement.timerOrPassTarget & 0x1) && !pTarget)
{
DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, " DB-SCRIPTS: Process table `%s` id %u, SCRIPT_COMMAND_MOVEMENT called for movement change to %u with source guid %s, pass target true and target nullptr: skipping.", m_table, m_script->id, m_script->movement.movementType, pSource->GetGuidStr().c_str());
break;
Expand All @@ -2073,28 +2073,43 @@ bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTa
}
break;
case WAYPOINT_MOTION_TYPE:
{
source->StopMoving();
source->GetMotionMaster()->Clear(false, true);
if (!m_script->movement.timerOrPassTarget)
WaypointPathOrigin origin = PATH_NO_PATH;
if (m_script->movement.timerOrPassTarget & 0x2)
origin = PATH_FROM_WAYPOINT_PATH;
if (!m_script->movement.timerOrPassTarget & 0x1)
source->GetMotionMaster()->MoveWaypoint(m_script->movement.wanderORpathId);
else
source->GetMotionMaster()->MoveWaypoint(m_script->movement.wanderORpathId, 0, 0, 0, ForcedMovement(m_script->textId[0]), pTarget->GetObjectGuid());
break;
}
case PATH_MOTION_TYPE:
{
source->StopMoving();
if (!m_script->movement.timerOrPassTarget)
WaypointPathOrigin origin = PATH_NO_PATH;
if (m_script->movement.timerOrPassTarget & 0x2)
origin = PATH_FROM_WAYPOINT_PATH;
if (!m_script->movement.timerOrPassTarget & 0x1)
source->GetMotionMaster()->MovePath(m_script->movement.wanderORpathId);
else
source->GetMotionMaster()->MovePath(m_script->movement.wanderORpathId, PATH_NO_PATH, ForcedMovement(m_script->textId[0]), false, 0.f, false, pTarget->GetObjectGuid());
break;
}
case LINEAR_WP_MOTION_TYPE:
{
source->StopMoving();
source->GetMotionMaster()->Clear(false, true);
if (!m_script->movement.timerOrPassTarget)
WaypointPathOrigin origin = PATH_NO_PATH;
if (m_script->movement.timerOrPassTarget & 0x2)
origin = PATH_FROM_WAYPOINT_PATH;
if (!m_script->movement.timerOrPassTarget & 0x1)
source->GetMotionMaster()->MoveLinearWP(m_script->movement.wanderORpathId);
else
source->GetMotionMaster()->MoveLinearWP(m_script->movement.wanderORpathId, 0, 0, 0, ForcedMovement(m_script->textId[0]), pTarget->GetObjectGuid());
break;
}
}

break;
Expand Down
37 changes: 34 additions & 3 deletions src/game/MotionGenerators/WaypointMovementGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "Movement/MoveSpline.h"
#include "Maps/GridDefines.h"
#include "Entities/Transports.h"
#include "AI/ScriptDevAI/base/escort_ai.h"

#include <cassert>

Expand Down Expand Up @@ -189,8 +190,18 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
// Inform script
if (creature.AI())
{
uint32 type = WAYPOINT_MOTION_TYPE;
bool inform = false;
if (m_PathOrigin == PATH_FROM_EXTERNAL)
inform = true;
else if (m_PathOrigin == PATH_FROM_WAYPOINT_PATH) // temporary transitional code for transitioning from script_texts to waypoint_path
{
if (npc_escortAI* ai = dynamic_cast<npc_escortAI*>(creature.AI()))
if (ai->GetCurrentWaypointPath() == m_pathId)
inform = true;
}

uint32 type = WAYPOINT_MOTION_TYPE;
if (inform)
type = EXTERNAL_WAYPOINT_MOVE;
InformAI(creature, type, i_currentNode);
}
Expand Down Expand Up @@ -226,8 +237,18 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
// Fire event only if it is already moving to the next node (for normal start it is already done in SendNewPath)
if (!m_nodeIndexes.empty() && !Stopped(creature))
{
bool inform = false;
if (m_PathOrigin == PATH_FROM_EXTERNAL)
inform = true;
else if (m_PathOrigin == PATH_FROM_WAYPOINT_PATH) // temporary transitional code for transitioning from script_texts to waypoint_path
{
if (npc_escortAI* ai = dynamic_cast<npc_escortAI*>(creature.AI()))
if (ai->GetCurrentWaypointPath() == m_pathId)
inform = true;
}

// Inform AI that we start to move
if (creature.AI() && m_PathOrigin == PATH_FROM_EXTERNAL)
if (creature.AI() && inform)
InformAI(creature, uint32(EXTERNAL_WAYPOINT_MOVE_START), m_currentWaypointNode->first);
}

Expand Down Expand Up @@ -307,8 +328,18 @@ void WaypointMovementGenerator<Creature>::SendNextWayPointPath(Creature& creatur

WaypointNode const* nextNode = &m_currentWaypointNode->second;

bool inform = false;
if (m_PathOrigin == PATH_FROM_EXTERNAL)
inform = true;
else if (m_PathOrigin == PATH_FROM_WAYPOINT_PATH) // temporary transitional code for transitioning from script_texts to waypoint_path
{
if (npc_escortAI* ai = dynamic_cast<npc_escortAI*>(creature.AI()))
if (ai->GetCurrentWaypointPath() == m_pathId)
inform = true;
}

// Inform AI that we start to move or reached last node
if (creature.AI() && m_PathOrigin == PATH_FROM_EXTERNAL)
if (creature.AI() && inform)
{
uint32 type = uint32(EXTERNAL_WAYPOINT_MOVE_START);
if (i_path->begin()->first == i_currentNode && i_path->rbegin()->first == m_lastReachedWaypoint)
Expand Down

0 comments on commit 63d9e7b

Please sign in to comment.