aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2018-08-20 19:04:21 +0200
committerShauren <shauren.trinity@gmail.com>2021-10-22 00:48:20 +0200
commit6a5edf04725502d749636fc6c6bb3935d83c222f (patch)
tree57c9f011bf9cebf68f27fb9a6691dc7b50d1e074 /src
parent2d72e79ac4ec30cc4754024ae67c956c8fedf4a2 (diff)
Core/AI: Some cleanup to DoZoneInCombat and Malygos' AI that I found while working out #22226.
(cherry picked from commit eb1972f21d6e79da32a89cb58c5c28eb98b0a4fb)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CreatureAI.cpp51
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp54
2 files changed, 30 insertions, 75 deletions
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 4e8e035bf5b..e3f3cabb5ef 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -67,49 +67,28 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange
creature = me;
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;
- }
-
- 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;
- }
+ 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;
}
Map::PlayerList const& playerList = map->GetPlayers();
if (playerList.isEmpty())
return;
- for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
- if (Player* player = itr->GetSource())
- if (player->IsAlive())
- creature->EngageWithTarget(player);
+ for (auto const& ref : playerList)
+ if (Player* player = ref.GetSource())
+ {
+ 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
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 5f85069674d..25416696d1f 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -355,7 +355,6 @@ public:
guid.Clear();
_killSpamFilter = false;
- _canAttack = false;
_executingVortex = false;
_arcaneReinforcements = true;
_flyingOutOfPlatform = false;
@@ -465,7 +464,6 @@ public:
alexstraszaBunny->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAbsoluteAngle(me));
me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos);
me->SetImmuneToAll(false);
- me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat();
events.ScheduleEvent(EVENT_LAND_START_ENCOUNTER, 7*IN_MILLISECONDS, 1, PHASE_NOT_STARTED);
}
@@ -560,13 +558,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
{
// We can't call full function here since it includes DoZoneInCombat(),
@@ -588,30 +579,10 @@ public:
void EnterEvadeMode(EvadeReason /*why*/) override
{
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);
- 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 (_phase == PHASE_TWO)
@@ -625,7 +596,7 @@ public:
summons.DespawnAll();
}
- instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED);
+ me->DespawnOrUnsummon(0, 30s);
}
void KilledUnit(Unit* victim) override
@@ -705,7 +676,7 @@ public:
case POINT_LAND_AFTER_VORTEX_P_ONE:
me->SetDisableGravity(false);
_executingVortex = false;
- _canAttack = true;
+ me->SetReactState(REACT_AGGRESSIVE);
break;
case POINT_LIFT_IN_AIR_P_ONE:
me->SetDisableGravity(true);
@@ -751,9 +722,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
{
- if (!instance || (!UpdateVictim() && _phase != PHASE_NOT_STARTED && _phase != PHASE_TWO))
+ if (!UpdateVictim() && _phase != PHASE_NOT_STARTED && _phase != PHASE_TWO)
return;
events.Update(diff);
@@ -766,7 +743,7 @@ public:
if (_phase == PHASE_ONE && me->GetHealthPct() <= 50.0f)
{
SetPhase(PHASE_TWO, true);
- _canAttack = false;
+ me->SetReactState(REACT_PASSIVE);
me->AttackStop();
Talk(SAY_END_P_ONE);
}
@@ -788,7 +765,7 @@ public:
me->SetFacingToObject(iris);
iris->Delete(); // this is not the best way.
}
- _canAttack = true;
+ me->SetReactState(REACT_AGGRESSIVE);
SetPhase(PHASE_ONE, true);
break;
case EVENT_SAY_INTRO:
@@ -801,7 +778,7 @@ public:
events.ScheduleEvent(EVENT_VORTEX, urand(60, 80)*IN_MILLISECONDS, 0, PHASE_ONE);
break;
case EVENT_MOVE_TO_VORTEX_POINT:
- _canAttack = false;
+ me->SetReactState(REACT_PASSIVE);
me->AttackStop();
me->GetMotionMaster()->MovePoint(POINT_VORTEX_P_ONE, MalygosPositions[1]);
break;
@@ -943,9 +920,9 @@ public:
me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1 * IN_MILLISECONDS);
DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
DoCast(me, SPELL_IMMUNE_CURSES);
- _canAttack = true;
- UpdateVictim();
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoZoneInCombat();
SetPhase(PHASE_THREE, true);
break;
case EVENT_SURGE_OF_POWER_P_THREE:
@@ -1022,7 +999,6 @@ public:
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 _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 _executingVortex; // Prevents some events being sheduled during Vortex takeoff/land.
bool _arcaneReinforcements; // Checks if 10 or 25 man arcane trash will be spawned.