Core/AI: Some cleanup to DoZoneInCombat and Malygos' AI that I found while working out #22226.

This commit is contained in:
Treeston
2018-08-20 19:04:21 +02:00
parent a8dd266704
commit eb1972f21d
2 changed files with 30 additions and 75 deletions

View File

@@ -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

View File

@@ -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.