fix(Core/Unit): rework Walk/Run mode (#22988)

Co-authored-by: sudlud <sudlud@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
killerwife
2025-10-14 22:54:19 +02:00
committed by GitHub
parent c28f635408
commit 10d5a3c553
104 changed files with 373 additions and 362 deletions

View File

@@ -43,9 +43,6 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
mCanRepeatPath = false;
// spawn in run mode
// Xinef: spawn in run mode and set mRun to run... this overrides SetWalk EVERYWHERE
mRun = true;
mEvadeDisabled = false;
mCanAutoAttack = true;
@@ -190,7 +187,7 @@ void SmartAI::GenerateWayPointArray(Movement::PointsArray* points)
}
}
void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
void SmartAI::StartPath(ForcedMovement forcedMovement, uint32 path, bool repeat, Unit* invoker)
{
if (HasEscortState(SMART_ESCORT_ESCORTING))
StopPath();
@@ -208,7 +205,6 @@ void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
{
AddEscortState(SMART_ESCORT_ESCORTING);
mCanRepeatPath = repeat;
SetRun(run);
if (invoker && invoker->IsPlayer())
{
@@ -219,7 +215,7 @@ void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
Movement::PointsArray pathPoints;
GenerateWayPointArray(&pathPoints);
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
me->GetMotionMaster()->MoveSplinePath(&pathPoints, forcedMovement);
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, wp->id, GetScript()->GetPathId());
}
}
@@ -256,7 +252,6 @@ void SmartAI::PausePath(uint32 delay, bool forced)
if (forced && !mWPReached)
{
mForcedPaused = forced;
SetRun(mRun);
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
@@ -362,7 +357,7 @@ void SmartAI::EndPath(bool fail)
if (mCanRepeatPath)
{
if (IsAIControlled())
StartPath(mRun, GetScript()->GetPathId(), true);
StartPath(FORCED_MOVEMENT_NONE, GetScript()->GetPathId(), true);
}
else
GetScript()->SetPathId(0);
@@ -373,8 +368,6 @@ void SmartAI::EndPath(bool fail)
void SmartAI::ResumePath()
{
SetRun(mRun);
if (mLastWP)
{
Movement::PointsArray pathPoints;
@@ -389,10 +382,9 @@ void SmartAI::ReturnToLastOOCPos()
if (!IsAIControlled())
return;
me->SetWalk(false);
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, x, y, z);
me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, x, y, z, FORCED_MOVEMENT_RUN);
}
void SmartAI::UpdatePath(const uint32 diff)
@@ -469,7 +461,6 @@ void SmartAI::UpdatePath(const uint32 diff)
EndPath();
else if (GetNextWayPoint())
{
SetRun(mRun);
// xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one
if (me->movespline->Finalized())
ResumePath();
@@ -629,7 +620,6 @@ void SmartAI::MovepointReached(uint32 id)
EndPath();
else if (GetNextWayPoint())
{
SetRun(mRun);
// xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one
if (me->movespline->Finalized())
ResumePath();
@@ -675,7 +665,6 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE); //must be after aura clear so we can cast spells from db
SetRun(mRun);
if (HasEscortState(SMART_ESCORT_ESCORTING))
{
AddEscortState(SMART_ESCORT_RETURNING);
@@ -850,7 +839,6 @@ void SmartAI::AttackStart(Unit* who)
{
if (!me->HasUnitState(UNIT_STATE_NO_COMBAT_MOVEMENT))
{
SetRun(mRun);
MovementGeneratorType type = me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE);
if (type == ESCORT_MOTION_TYPE || type == POINT_MOTION_TYPE)
{
@@ -952,9 +940,7 @@ void SmartAI::OnCharmed(bool /* apply */)
if (!charmed && !me->IsInEvadeMode())
{
if (mCanRepeatPath)
StartPath(mRun, GetScript()->GetPathId(), true);
else
me->SetWalk(!mRun);
StartPath(FORCED_MOVEMENT_NONE, GetScript()->GetPathId(), true);
if (Unit* charmer = me->GetCharmer())
AttackStart(charmer);
@@ -1002,12 +988,6 @@ ObjectGuid SmartAI::GetGUID(int32 /*id*/) const
return ObjectGuid::Empty;
}
void SmartAI::SetRun(bool run)
{
me->SetWalk(!run);
mRun = run;
}
void SmartAI::SetFly(bool fly)
{
// xinef: set proper flag!
@@ -1108,7 +1088,6 @@ void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, ui
mFollowArrivedEntry = end;
mFollowArrivedAlive = !aliveState; // negate - 0 is alive
mFollowCreditType = creditType;
SetRun(mRun);
me->GetMotionMaster()->MoveFollow(target, mFollowDist, mFollowAngle);
}

View File

@@ -52,7 +52,7 @@ public:
bool IsAIControlled() const;
// Start moving to the desired MovePoint
void StartPath(bool run = false, uint32 path = 0, bool repeat = false, Unit* invoker = nullptr);
void StartPath(ForcedMovement forcedMovement = FORCED_MOVEMENT_NONE, uint32 path = 0, bool repeat = false, Unit* invoker = nullptr);
bool LoadPath(uint32 entry);
void PausePath(uint32 delay, bool forced = false);
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
@@ -175,9 +175,6 @@ public:
// Called at movepoint reached
void MovepointReached(uint32 id);
// Makes the creature run/walk
void SetRun(bool run = true);
void SetFly(bool fly = true);
void SetSwim(bool swim = true);
@@ -240,7 +237,6 @@ private:
uint32 mEscortNPCFlags;
uint32 GetWPCount() { return mWayPoints ? mWayPoints->size() : 0; }
bool mCanRepeatPath;
bool mRun;
bool mEvadeDisabled;
bool mCanAutoAttack;
bool mForcedPaused;

View File

@@ -1683,10 +1683,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (IsCreature(target))
{
if (IsSmart(target->ToCreature()))
CAST_AI(SmartAI, target->ToCreature()->AI())->SetRun(e.action.setRun.run);
else
target->ToCreature()->SetWalk(e.action.setRun.run ? false : true); // Xinef: reversed
target->ToCreature()->SetWalk(e.action.setRun.run ? false : true);
}
}
@@ -1731,7 +1728,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!IsSmart())
break;
bool run = e.action.wpStart.run != 0;
ForcedMovement forcedMovement = static_cast<ForcedMovement>(e.action.wpStart.forcedMovement);
uint32 entry = e.action.wpStart.pathID;
bool repeat = e.action.wpStart.repeat != 0;
@@ -1745,7 +1742,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
me->SetReactState((ReactStates)e.action.wpStart.reactState);
CAST_AI(SmartAI, me->AI())->StartPath(run, entry, repeat, unit);
CAST_AI(SmartAI, me->AI())->StartPath(forcedMovement, entry, repeat, unit);
uint32 quest = e.action.wpStart.quest;
uint32 DespawnTime = e.action.wpStart.despawnTime;
@@ -1854,8 +1851,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (TransportBase* trans = me->GetDirectTransport())
trans->CalculatePassengerPosition(dest.x, dest.y, dest.z);
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, isForced,
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o);
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, FORCED_MOVEMENT_NONE,
0.f, e.target.o, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
break;
}
@@ -1871,9 +1868,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
randomPoint.m_positionX,
randomPoint.m_positionY,
randomPoint.m_positionZ,
true,
isForced,
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE
FORCED_MOVEMENT_NONE,
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE
);
}
@@ -1897,7 +1893,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
else if (e.action.moveToPos.ContactDistance)
target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me));
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, FORCED_MOVEMENT_NONE,
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
break;
}
@@ -1914,7 +1911,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
SAIBool isForced = !e.action.moveToPosTarget.disableForceDestination;
Creature* ctarget = target->ToCreature();
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPosTarget.pointId, e.target.x, e.target.y, e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPosTarget.pointId, e.target.x, e.target.y, e.target.z, FORCED_MOVEMENT_NONE,
0.f, 0.f, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
}
}
@@ -2543,9 +2541,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (closestWpId)
{
bool repeat = e.action.startClosestWaypoint.repeat;
bool run = e.action.startClosestWaypoint.run;
ForcedMovement forcedMovement = static_cast<ForcedMovement>(e.action.startClosestWaypoint.forcedMovement);
CAST_AI(SmartAI, creature->AI())->StartPath(repeat, closestWpId, run);
CAST_AI(SmartAI, creature->AI())->StartPath(forcedMovement, closestWpId, repeat);
}
}
}

View File

@@ -1564,11 +1564,11 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
return false;
}
if (e.action.startClosestWaypoint.repeat > 1 || e.action.startClosestWaypoint.run > 1)
if (e.action.startClosestWaypoint.repeat > 1 || e.action.startClosestWaypoint.forcedMovement >= FORCED_MOVEMENT_MAX)
{
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invalid run ({}) or repeat ({}) parameter, must be 0 or 1.",
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invalid forcedMovement ({}) or repeat ({}) parameter, must be 0 or 1.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(),
e.action.startClosestWaypoint.repeat, e.action.startClosestWaypoint.run);
e.action.startClosestWaypoint.repeat, e.action.startClosestWaypoint.forcedMovement);
return false;
}
break;
@@ -1745,8 +1745,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
return IsSAIBoolValid(e, e.action.wpStart.run) &&
IsSAIBoolValid(e, e.action.wpStart.repeat);
if (e.action.wpStart.forcedMovement >= FORCED_MOVEMENT_MAX)
{
LOG_ERROR("sql.sql", "SmartAIMgr: Creature {} Event {} Action {} uses invalid forcedMovement {}, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.forcedMovement);
return false;
}
return IsSAIBoolValid(e, e.action.wpStart.repeat);
}
case SMART_ACTION_CREATE_TIMED_EVENT:
{

View File

@@ -1041,7 +1041,7 @@ struct SmartAction
struct
{
SAIBool run;
uint32 forcedMovement;
uint32 pathID;
SAIBool repeat;
uint32 quest;
@@ -1295,7 +1295,7 @@ struct SmartAction
uint32 pathId1;
uint32 pathId2;
uint32 repeat;
uint32 run;
uint32 forcedMovement;
} startClosestWaypoint;
struct