mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-24 06:06:23 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user