Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
Yunfan Li
2024-03-19 20:12:59 +08:00
committed by GitHub
10 changed files with 4320 additions and 50 deletions

View File

@@ -21,6 +21,7 @@
#include "Log.h"
#include "MoveSplineInit.h"
#include "ObjectMgr.h"
#include "WaypointMgr.h"
FormationMgr::~FormationMgr()
{
@@ -290,41 +291,27 @@ void CreatureGroup::MemberEvaded(Creature* member)
Creature* pMember = itr.first;
// This should never happen
if (!pMember)
{
continue;
}
if (pMember == member || pMember->IsInEvadeMode() || !itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_EVADE_MASK)))
{
continue;
}
if (itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_EVADE_TOGETHER)))
{
if (!pMember->IsAlive() || !pMember->IsInCombat())
{
continue;
}
if (pMember->IsAIEnabled)
{
if (CreatureAI* pMemberAI = pMember->AI())
{
pMemberAI->EnterEvadeMode();
}
}
}
else
{
if (pMember->IsAlive())
{
continue;
}
if (itr.second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE)) && pMember == m_leader)
{
continue;
}
pMember->Respawn();
}
@@ -334,9 +321,7 @@ void CreatureGroup::MemberEvaded(Creature* member)
void CreatureGroup::FormationReset(bool dismiss, bool initMotionMaster)
{
if (m_members.size() && !(m_members.begin()->second.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_FOLLOW_LEADER))))
{
return;
}
for (auto const& itr : m_members)
{
@@ -346,13 +331,10 @@ void CreatureGroup::FormationReset(bool dismiss, bool initMotionMaster)
if (initMotionMaster)
{
if (dismiss)
{
member->GetMotionMaster()->Initialize();
}
else
{
member->GetMotionMaster()->MoveIdle();
}
LOG_DEBUG("entities.unit", "Set {} movement for member {}", dismiss ? "default" : "idle", member->GetGUID().ToString());
}
}
@@ -360,14 +342,12 @@ void CreatureGroup::FormationReset(bool dismiss, bool initMotionMaster)
m_Formed = !dismiss;
}
void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run)
void CreatureGroup::LeaderMoveTo(float x, float y, float z, uint32 move_type)
{
//! To do: This should probably get its own movement generator or use WaypointMovementGenerator.
//! If the leader's path is known, member's path can be plotted as well using formation offsets.
if (!m_leader)
{
return;
}
float pathDist = m_leader->GetExactDist(x, y, z);
float pathAngle = std::atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
@@ -377,15 +357,11 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run)
Creature* member = itr.first;
FormationInfo const& pFormationInfo = itr.second;
if (member == m_leader || !member->IsAlive() || member->GetVictim() || !pFormationInfo.HasGroupFlag(std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_FOLLOW_LEADER)))
{
continue;
}
// Xinef: If member is stunned / rooted etc don't allow to move him
if (member->HasUnitState(UNIT_STATE_NOT_MOVE))
{
continue;
}
// Xinef: this should be automatized, if turn angle is greater than PI/2 (90<39>) we should swap formation angle
float followAngle = pFormationInfo.follow_angle;
@@ -406,17 +382,22 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run)
Acore::NormalizeMapCoord(dx);
Acore::NormalizeMapCoord(dy);
member->UpdateGroundPositionZ(dx, dy, dz);
if (move_type < 2)
member->UpdateGroundPositionZ(dx, dy, dz);
member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
// pussywizard: setting the same movementflags is not enough, spline decides whether leader walks/runs, so spline param is now passed as "run" parameter to this function
if (run && member->IsWalking())
{
member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
}
else if (!run && !member->IsWalking())
member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
switch (move_type)
{
case WAYPOINT_MOVE_TYPE_WALK:
member->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
break;
case WAYPOINT_MOVE_TYPE_RUN:
member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
break;
case WAYPOINT_MOVE_TYPE_LAND:
member->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
break;
}
// xinef: if we move members to position without taking care of sizes, we should compare distance without sizes

View File

@@ -107,7 +107,7 @@ public:
void RemoveMember(Creature* member);
void FormationReset(bool dismiss, bool initMotionMaster);
void LeaderMoveTo(float x, float y, float z, bool run);
void LeaderMoveTo(float x, float y, float z, uint32 move_type);
void MemberEngagingTarget(Creature* member, Unit* target);
Unit* GetNewTargetForMember(Creature* member);
void MemberEvaded(Creature* member);

View File

@@ -54,7 +54,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
init.SetWalk(true);
init.Launch();
if (creature->GetFormation() && creature->GetFormation()->GetLeader() == creature)
creature->GetFormation()->LeaderMoveTo(_currDestPosition.GetPositionX(), _currDestPosition.GetPositionY(), _currDestPosition.GetPositionZ(), false);
creature->GetFormation()->LeaderMoveTo(_currDestPosition.GetPositionX(), _currDestPosition.GetPositionY(), _currDestPosition.GetPositionZ(), 0);
return;
}
@@ -230,7 +230,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
//Call for creature group update
if (creature->GetFormation() && creature->GetFormation()->GetLeader() == creature)
creature->GetFormation()->LeaderMoveTo(finalPoint.x, finalPoint.y, finalPoint.z, false);
creature->GetFormation()->LeaderMoveTo(finalPoint.x, finalPoint.y, finalPoint.z, 0);
}
template<>

View File

@@ -200,7 +200,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
//Call for creature group update
if (creature->GetFormation() && creature->GetFormation()->GetLeader() == creature)
creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z, node->move_type == WAYPOINT_MOVE_TYPE_RUN);
creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z, node->move_type);
return true;
}

View File

@@ -151,8 +151,9 @@ enum Misc
PHASE_NONE = 0,
PHASE_SINGLE_ADVISOR = 1,
PHASE_WEAPONS = 2,
PHASE_ALL_ADVISORS = 3,
PHASE_FINAL = 4,
PHASE_TRANSITION = 3,
PHASE_ALL_ADVISORS = 4,
PHASE_FINAL = 5,
EVENT_PREFIGHT_PHASE11 = 1,
EVENT_PREFIGHT_PHASE12 = 2,
@@ -352,6 +353,8 @@ struct boss_kaelthas : public BossAI
summons.Summon(summon);
if (summon->GetEntry() == NPC_NETHER_VAPOR)
summon->GetMotionMaster()->MoveRandom(20.0f);
if (summon->GetEntry() >= NPC_NETHERSTRAND_LONGBOW && summon->GetEntry() <= NPC_STAFF_OF_DISINTEGRATION)
summon->SetReactState(REACT_PASSIVE);
}
void DoAction(int32 action) override
@@ -380,7 +383,7 @@ struct boss_kaelthas : public BossAI
{
if (!summonedCreature->GetSpawnId())
{
summonedCreature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
summonedCreature->SetReactState(REACT_AGGRESSIVE);
summonedCreature->SetInCombatWithZone();
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
@@ -678,13 +681,14 @@ struct boss_kaelthas : public BossAI
void PhaseAllAdvisorsExecute()
{
_phase = PHASE_TRANSITION;
scheduler.CancelGroup(GROUP_PROGRESS_PHASE);
_phase = PHASE_ALL_ADVISORS;
Talk(SAY_PHASE3_ADVANCE);
ScheduleUniqueTimedEvent(6s, [&]{
DoCastSelf(SPELL_RESURRECTION);
}, EVENT_PREFIGHT_PHASE62);
ScheduleUniqueTimedEvent(12s, [&]{
_phase = PHASE_ALL_ADVISORS;
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
@@ -743,18 +747,16 @@ struct boss_kaelthas : public BossAI
DoCastSelf(SPELL_ARCANE_DISRUPTION);
});
}, 50s);
ScheduleTimedEvent(40s, [&]
ScheduleTimedEvent(43s, [&]
{
if (roll_chance_i(50))
Talk(SAY_MINDCONTROL);
me->CastCustomSpell(SPELL_MIND_CONTROL, SPELLVALUE_MAX_TARGETS, 3, me, false);
scheduler.Schedule(3s, [this](TaskContext)
{
if (roll_chance_i(50))
Talk(SAY_MINDCONTROL);
me->CastCustomSpell(SPELL_MIND_CONTROL, SPELLVALUE_MAX_TARGETS, 3, me, false);
}).Schedule(6s, [this](TaskContext)
{
DoCastSelf(SPELL_ARCANE_DISRUPTION);
});
}, 50s);
}, 53s);
ScheduleTimedEvent(60s, [&]
{
Talk(SAY_PYROBLAST);
@@ -1041,7 +1043,7 @@ struct npc_thaladred : public ScriptedAI
{
DoCastVictim(SPELL_REND);
}, 15700ms, 48900ms);
ScheduleTimedEvent(3000ms,6050ms, [&]
ScheduleTimedEvent(3000ms, 6050ms, [&]
{
if (Unit* victim = me->GetVictim())
{