mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/AI: Some cleanup to DoZoneInCombat and Malygos' AI that I found while working out #22226.
This commit is contained in:
@@ -64,49 +64,28 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
|
|||||||
creature = me;
|
creature = me;
|
||||||
|
|
||||||
Map* map = creature->GetMap();
|
Map* map = creature->GetMap();
|
||||||
if (creature->CanHaveThreatList())
|
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
|
||||||
{
|
{
|
||||||
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
|
TC_LOG_ERROR("misc", "DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
|
||||||
{
|
return;
|
||||||
TC_LOG_ERROR("misc", "DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
|
|
||||||
{
|
|
||||||
if (Unit* nearTarget = creature->SelectNearestTarget(maxRangeToNearestTarget))
|
|
||||||
creature->AI()->AttackStart(nearTarget);
|
|
||||||
else if (creature->IsSummon())
|
|
||||||
{
|
|
||||||
if (Unit* summoner = creature->ToTempSummon()->GetSummoner())
|
|
||||||
{
|
|
||||||
if (creature->IsFriendlyTo(summoner))
|
|
||||||
{
|
|
||||||
Unit* target = summoner->getAttackerForHelper();
|
|
||||||
if (target && creature->IsHostileTo(target))
|
|
||||||
creature->AI()->AttackStart(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intended duplicated check, the code above this should select a victim
|
|
||||||
// If it can't find a suitable attack target then we should error out.
|
|
||||||
if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
|
|
||||||
{
|
|
||||||
TC_LOG_ERROR("misc.dozoneincombat", "DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map::PlayerList const& playerList = map->GetPlayers();
|
Map::PlayerList const& playerList = map->GetPlayers();
|
||||||
if (playerList.isEmpty())
|
if (playerList.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
|
for (auto const& ref : playerList)
|
||||||
if (Player* player = itr->GetSource())
|
if (Player* player = ref.GetSource())
|
||||||
if (player->IsAlive())
|
{
|
||||||
creature->EngageWithTarget(player);
|
if (!player->IsAlive() || !CombatManager::CanBeginCombat(creature, player))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
creature->EngageWithTarget(player);
|
||||||
|
for (Unit* pet : player->m_Controlled)
|
||||||
|
creature->EngageWithTarget(pet);
|
||||||
|
if (Unit* vehicle = player->GetVehicleBase())
|
||||||
|
creature->EngageWithTarget(vehicle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// scripts does not take care about MoveInLineOfSight loops
|
// scripts does not take care about MoveInLineOfSight loops
|
||||||
|
|||||||
@@ -357,7 +357,6 @@ public:
|
|||||||
guid.Clear();
|
guid.Clear();
|
||||||
|
|
||||||
_killSpamFilter = false;
|
_killSpamFilter = false;
|
||||||
_canAttack = false;
|
|
||||||
_executingVortex = false;
|
_executingVortex = false;
|
||||||
_arcaneReinforcements = true;
|
_arcaneReinforcements = true;
|
||||||
_flyingOutOfPlatform = false;
|
_flyingOutOfPlatform = false;
|
||||||
@@ -467,7 +466,6 @@ public:
|
|||||||
alexstraszaBunny->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAbsoluteAngle(me));
|
alexstraszaBunny->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAbsoluteAngle(me));
|
||||||
me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos);
|
me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos);
|
||||||
me->SetImmuneToAll(false);
|
me->SetImmuneToAll(false);
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
|
||||||
DoZoneInCombat();
|
DoZoneInCombat();
|
||||||
events.ScheduleEvent(EVENT_LAND_START_ENCOUNTER, 7*IN_MILLISECONDS, 1, PHASE_NOT_STARTED);
|
events.ScheduleEvent(EVENT_LAND_START_ENCOUNTER, 7*IN_MILLISECONDS, 1, PHASE_NOT_STARTED);
|
||||||
}
|
}
|
||||||
@@ -562,13 +560,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are moments where boss will do nothing while being attacked
|
|
||||||
void AttackStart(Unit* target) override
|
|
||||||
{
|
|
||||||
if (_canAttack)
|
|
||||||
BossAI::AttackStart(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
{
|
{
|
||||||
// We can't call full function here since it includes DoZoneInCombat(),
|
// We can't call full function here since it includes DoZoneInCombat(),
|
||||||
@@ -590,30 +581,10 @@ public:
|
|||||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
{
|
{
|
||||||
instance->SetBossState(DATA_MALYGOS_EVENT, FAIL);
|
instance->SetBossState(DATA_MALYGOS_EVENT, FAIL);
|
||||||
|
instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED);
|
||||||
|
|
||||||
me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS);
|
me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS);
|
||||||
|
|
||||||
if (_phase == PHASE_THREE)
|
|
||||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
|
||||||
|
|
||||||
uint32 corpseDelay = me->GetCorpseDelay();
|
|
||||||
uint32 respawnDelay = me->GetRespawnDelay();
|
|
||||||
me->SetCorpseDelay(1);
|
|
||||||
me->SetRespawnDelay(29);
|
|
||||||
me->DespawnOrUnsummon();
|
|
||||||
me->SetCorpseDelay(corpseDelay);
|
|
||||||
me->SetRespawnDelay(respawnDelay);
|
|
||||||
|
|
||||||
// Set speed to normal value
|
|
||||||
me->SetSpeedRate(MOVE_FLIGHT, _flySpeed);
|
|
||||||
me->RemoveAllAuras();
|
|
||||||
me->CombatStop(); // Sometimes threat can remain, so it's a safety measure
|
|
||||||
|
|
||||||
if (!_despawned)
|
|
||||||
_despawned = true;
|
|
||||||
|
|
||||||
me->ResetLootMode();
|
|
||||||
events.Reset();
|
|
||||||
if (!summons.empty())
|
if (!summons.empty())
|
||||||
{
|
{
|
||||||
if (_phase == PHASE_TWO)
|
if (_phase == PHASE_TWO)
|
||||||
@@ -627,7 +598,7 @@ public:
|
|||||||
summons.DespawnAll();
|
summons.DespawnAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED);
|
me->DespawnOrUnsummon(0, 30s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
@@ -707,7 +678,7 @@ public:
|
|||||||
case POINT_LAND_AFTER_VORTEX_P_ONE:
|
case POINT_LAND_AFTER_VORTEX_P_ONE:
|
||||||
me->SetDisableGravity(false);
|
me->SetDisableGravity(false);
|
||||||
_executingVortex = false;
|
_executingVortex = false;
|
||||||
_canAttack = true;
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
break;
|
break;
|
||||||
case POINT_LIFT_IN_AIR_P_ONE:
|
case POINT_LIFT_IN_AIR_P_ONE:
|
||||||
me->SetDisableGravity(true);
|
me->SetDisableGravity(true);
|
||||||
@@ -753,9 +724,15 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*cause*/, uint32& damage) override
|
||||||
|
{
|
||||||
|
if (damage > me->GetHealth() && _phase != PHASE_THREE)
|
||||||
|
damage = me->GetHealth() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!instance || (!UpdateVictim() && _phase != PHASE_NOT_STARTED && _phase != PHASE_TWO))
|
if (!UpdateVictim() && _phase != PHASE_NOT_STARTED && _phase != PHASE_TWO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
@@ -768,7 +745,7 @@ public:
|
|||||||
if (_phase == PHASE_ONE && me->GetHealthPct() <= 50.0f)
|
if (_phase == PHASE_ONE && me->GetHealthPct() <= 50.0f)
|
||||||
{
|
{
|
||||||
SetPhase(PHASE_TWO, true);
|
SetPhase(PHASE_TWO, true);
|
||||||
_canAttack = false;
|
me->SetReactState(REACT_PASSIVE);
|
||||||
me->AttackStop();
|
me->AttackStop();
|
||||||
Talk(SAY_END_P_ONE);
|
Talk(SAY_END_P_ONE);
|
||||||
}
|
}
|
||||||
@@ -790,7 +767,7 @@ public:
|
|||||||
me->SetFacingToObject(iris);
|
me->SetFacingToObject(iris);
|
||||||
iris->Delete(); // this is not the best way.
|
iris->Delete(); // this is not the best way.
|
||||||
}
|
}
|
||||||
_canAttack = true;
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
SetPhase(PHASE_ONE, true);
|
SetPhase(PHASE_ONE, true);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAY_INTRO:
|
case EVENT_SAY_INTRO:
|
||||||
@@ -803,7 +780,7 @@ public:
|
|||||||
events.ScheduleEvent(EVENT_VORTEX, urand(60, 80)*IN_MILLISECONDS, 0, PHASE_ONE);
|
events.ScheduleEvent(EVENT_VORTEX, urand(60, 80)*IN_MILLISECONDS, 0, PHASE_ONE);
|
||||||
break;
|
break;
|
||||||
case EVENT_MOVE_TO_VORTEX_POINT:
|
case EVENT_MOVE_TO_VORTEX_POINT:
|
||||||
_canAttack = false;
|
me->SetReactState(REACT_PASSIVE);
|
||||||
me->AttackStop();
|
me->AttackStop();
|
||||||
me->GetMotionMaster()->MovePoint(POINT_VORTEX_P_ONE, MalygosPositions[1]);
|
me->GetMotionMaster()->MovePoint(POINT_VORTEX_P_ONE, MalygosPositions[1]);
|
||||||
break;
|
break;
|
||||||
@@ -945,9 +922,9 @@ public:
|
|||||||
me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1 * IN_MILLISECONDS);
|
me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1 * IN_MILLISECONDS);
|
||||||
DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
|
DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
|
||||||
DoCast(me, SPELL_IMMUNE_CURSES);
|
DoCast(me, SPELL_IMMUNE_CURSES);
|
||||||
_canAttack = true;
|
|
||||||
UpdateVictim();
|
|
||||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
DoZoneInCombat();
|
||||||
SetPhase(PHASE_THREE, true);
|
SetPhase(PHASE_THREE, true);
|
||||||
break;
|
break;
|
||||||
case EVENT_SURGE_OF_POWER_P_THREE:
|
case EVENT_SURGE_OF_POWER_P_THREE:
|
||||||
@@ -1017,7 +994,6 @@ public:
|
|||||||
ObjectGuid _surgeTargetGUID[3]; // All these three are used to keep current tagets to which warning should be sent.
|
ObjectGuid _surgeTargetGUID[3]; // All these three are used to keep current tagets to which warning should be sent.
|
||||||
|
|
||||||
bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD.
|
bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD.
|
||||||
bool _canAttack; // Used to control attacking (Move Chase not being applied after Stop Attack, only few times should act like this).
|
|
||||||
bool _despawned; // Checks if boss pass through evade on reset.
|
bool _despawned; // Checks if boss pass through evade on reset.
|
||||||
bool _executingVortex; // Prevents some events being sheduled during Vortex takeoff/land.
|
bool _executingVortex; // Prevents some events being sheduled during Vortex takeoff/land.
|
||||||
bool _arcaneReinforcements; // Checks if 10 or 25 man arcane trash will be spawned.
|
bool _arcaneReinforcements; // Checks if 10 or 25 man arcane trash will be spawned.
|
||||||
|
|||||||
Reference in New Issue
Block a user