Core/Creatures: Moved autoattack handling from scripts to game

This commit is contained in:
Shauren
2024-01-08 22:23:12 +01:00
parent eeb4407f07
commit 605e5f94c0
425 changed files with 393 additions and 1816 deletions
@@ -0,0 +1,90 @@
UPDATE `creature_template_difficulty` SET `StaticFlags1`=`StaticFlags1`|0x100000 WHERE `Entry` IN (
15589, -- Eye of C'Thun
15727, -- C'Thun
16129, -- Shadow Fissure
16474, -- Blizzard
17096, -- Astral Flare
17907, -- Frost Wyrm
17990, -- Underbog Mushroom
18412, -- Cyclone (The Crone)
18729, -- Infernal Rain (Hellfire)
19427, -- Voidwalker Summoner
19781, -- Astral Flare
19782, -- Astral Flare
19783, -- Astral Flare
21364, -- Phoenix Egg
22950, -- High Nethermancer Zerevor
23417, -- Reliquary Combat Trigger
23426, -- The Illidari Council
25265, -- Demonic Vapor
25267, -- Demonic Vapor (Trail)
25502, -- Shield Orb
25603, -- Felfire Portal
25741, -- M'uru
25744, -- Dark Fiend
25855, -- Singularity
27629, -- Wyrmrest Defender
27692, -- Emerald Drake
27755, -- Amber Drake
27756, -- Ruby Drake
28926, -- Spark of Ionar
29271, -- Ethereal Sphere
30234, -- Hover Disk
30249, -- Scion of Eternity
30391, -- Healthy Mushroom
30435, -- Poisonous Mushroom
30616, -- Flame Tsunami
30641, -- Twilight Fissure
30882, -- Twilight Egg
31216, -- Mirror Image
32582, -- Ethereal Sphere
33052, -- Living Constellation
33090, -- Pool of Tar
33134, -- Sara
33139, -- Flame Leviathan Turret
33169, -- Icicle
33173, -- Snowpacked Icicle
33229, -- Melee Target
33243, -- Ranged Target
33272, -- Charge Target
33280, -- Voice of Yogg-Saron
33552, -- Yogg-Saron
33651, -- VX-001
33670, -- Aerial Command Unit
33983, -- Constrictor Tentacle
33985, -- Corruptor Tentacle
33990, -- Laughing Skull
34441, -- Vivienne Blackwhisper
34444, -- Thrakgar
34445, -- Liandra Suncaller
34447, -- Caiphus the Stern
34449, -- Ginselle Blightslinger
34450, -- Harkzog
34451, -- Birana Stormhoof
34459, -- Erin Misthoof
34460, -- Kavina Grovesong
34465, -- Velanaa
34466, -- Anthar Forgemender
34468, -- Noozle Whizzlestick
34469, -- Melador Valestrider
34470, -- Saamul
34473, -- Brienna Nightfell
34474, -- Serissa Grimdabbler
34628, -- Concentrated Darkness
34630, -- Concentrated Light
34660, -- Anub'arak (Spike)
36549, -- Beasts Combat Stalker
36672, -- Coldflame
36855, -- Lady Deathwhisper
36968, -- Kor'kron Axethrower
36969, -- Skybreaker Rifleman
36978, -- Skybreaker Mortar Soldier
36980, -- Ice Tomb
36982, -- Kor'kron Rocketeer
37116, -- Skybreaker Sorcerer
37117, -- Kor'kron Battle-Mage
38008, -- Blood Orb Controller
38332, -- Ball of Flame
38451, -- Ball of Inferno Flame
38454 -- Kinetic Bomb
);
+3 -6
View File
@@ -43,10 +43,7 @@ int32 AggressorAI::Permissible(Creature const* creature)
void AggressorAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
/////////////////
@@ -107,8 +104,6 @@ void CombatAI::UpdateAI(uint32 diff)
if (AISpellInfoType const* info = GetAISpellInfo(spellId, me->GetMap()->GetDifficultyID()))
_events.ScheduleEvent(spellId, info->cooldown, info->cooldown * 2);
}
else
DoMeleeAttackIfReady();
}
void CombatAI::SpellInterrupted(uint32 spellId, uint32 unTimeMs)
@@ -202,6 +197,7 @@ TurretAI::TurretAI(Creature* creature, uint32 scriptId) : CreatureAI(creature, s
_minimumRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
creature->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
creature->m_SightDistance = creature->m_CombatDistance;
creature->SetCanMelee(false);
}
bool TurretAI::CanAIAttack(Unit const* who) const
@@ -235,6 +231,7 @@ VehicleAI::VehicleAI(Creature* creature, uint32 scriptId) : CreatureAI(creature,
LoadConditions();
_dismiss = false;
_dismissTimer = VEHICLE_DISMISS_TIME;
me->SetCanMelee(false);
}
// NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted
+1 -4
View File
@@ -31,10 +31,7 @@ int32 GuardAI::Permissible(Creature const* creature)
void GuardAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
bool GuardAI::CanSeeAlways(WorldObject const* obj)
+2 -2
View File
@@ -22,6 +22,7 @@
PassiveAI::PassiveAI(Creature* c, uint32 scriptId) : CreatureAI(c, scriptId)
{
me->SetReactState(REACT_PASSIVE);
me->SetCanMelee(false);
}
PossessedAI::PossessedAI(Creature* c, uint32 scriptId) : CreatureAI(c, scriptId)
@@ -32,6 +33,7 @@ PossessedAI::PossessedAI(Creature* c, uint32 scriptId) : CreatureAI(c, scriptId)
NullCreatureAI::NullCreatureAI(Creature* c, uint32 scriptId) : CreatureAI(c, scriptId)
{
me->SetReactState(REACT_PASSIVE);
me->SetCanMelee(false);
}
int32 NullCreatureAI::Permissible(Creature const* creature)
@@ -62,8 +64,6 @@ void PossessedAI::UpdateAI(uint32 /*diff*/)
{
if (!me->IsValidAttackTarget(me->GetVictim()))
me->AttackStop();
else
DoMeleeAttackIfReady();
}
}
-9
View File
@@ -80,15 +80,6 @@ void PetAI::UpdateAI(uint32 diff)
StopAttack();
return;
}
// Check before attacking to prevent pets from leaving stay position
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (me->GetCharmInfo()->IsCommandAttack() || (me->GetCharmInfo()->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
DoMeleeAttackIfReady();
}
else
DoMeleeAttackIfReady();
}
else
{
+1 -4
View File
@@ -28,8 +28,5 @@ int32 ReactorAI::Permissible(Creature const* creature)
void ReactorAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
-35
View File
@@ -58,41 +58,6 @@ void UnitAI::AttackStartCaster(Unit* victim, float dist)
me->GetMotionMaster()->MoveChase(victim, dist);
}
void UnitAI::DoMeleeAttackIfReady()
{
if (me->IsCreature() && !me->ToCreature()->CanMelee())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
{
Spell* channeledSpell = me->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
if (!channeledSpell || !channeledSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_ALLOW_ACTIONS_DURING_CHANNEL))
return;
}
Unit* victim = me->GetVictim();
if (!me->IsWithinMeleeRange(victim))
return;
// Check that the victim is in front of the unit
if (!me->HasInArc(2 * float(M_PI) / 3, victim))
return;
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady())
{
me->AttackerStateUpdate(victim);
me->resetAttackTimer();
}
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
{
me->AttackerStateUpdate(victim, OFF_ATTACK);
me->resetAttackTimer(OFF_ATTACK);
}
}
bool UnitAI::DoSpellAttackIfReady(uint32 spellId)
{
if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady())
-1
View File
@@ -160,7 +160,6 @@ class TC_GAME_API UnitAI
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const& args = {});
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const& args = {}) { return DoCast(nullptr, spellId, args); }
void DoMeleeAttackIfReady();
bool DoSpellAttackIfReady(uint32 spellId);
static std::unordered_map<std::pair<uint32, Difficulty>, AISpellInfoType> AISpellInfo;
-2
View File
@@ -591,8 +591,6 @@ void PlayerAI::DoAutoAttackIfReady()
{
if (IsRangedAttacker())
DoRangedAttackIfReady();
else
DoMeleeAttackIfReady();
}
void PlayerAI::CancelAllShapeshifts()
@@ -149,10 +149,7 @@ void ScriptedAI::AttackStart(Unit* who)
void ScriptedAI::UpdateAI(uint32 /*diff*/)
{
// Check if we have a current target
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
@@ -629,8 +626,6 @@ void BossAI::UpdateAI(uint32 diff)
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
bool BossAI::CanAIAttack(Unit const* target) const
@@ -716,6 +711,4 @@ void WorldBossAI::UpdateAI(uint32 diff)
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
@@ -248,10 +248,7 @@ void EscortAI::UpdateAI(uint32 diff)
void EscortAI::UpdateEscortAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
void EscortAI::AddWaypoint(uint32 id, float x, float y, float z, bool run)
@@ -147,10 +147,7 @@ void FollowerAI::UpdateAI(uint32 uiDiff)
void FollowerAI::UpdateFollowerAI(uint32 /*uiDiff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, uint32 quest)
+1 -9
View File
@@ -283,21 +283,13 @@ void SmartAI::UpdateAI(uint32 diff)
CheckConditions(diff);
bool hasVictim = UpdateVictim();
UpdateVictim();
GetScript()->OnUpdate(diff);
UpdatePath(diff);
UpdateFollow(diff);
UpdateDespawn(diff);
if (!IsAIControlled())
return;
if (!hasVictim)
return;
DoMeleeAttackIfReady();
}
bool SmartAI::IsEscortInvokerInRange()
@@ -852,6 +852,8 @@ void Creature::Update(uint32 diff)
Unit::AIUpdateTick(diff);
DoMeleeAttackIfReady();
// creature can be dead after UpdateAI call
// CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
if (!IsAlive())
+5 -90
View File
@@ -235,8 +235,6 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
m_deathTimer = 0;
m_deathExpireTime = 0;
m_swingErrorMsg = 0;
for (uint8 j = 0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; ++j)
{
m_bgBattlegroundQueueID[j].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
@@ -1011,78 +1009,7 @@ void Player::Update(uint32 p_time)
m_achievementMgr->UpdateTimedCriteria(Milliseconds(p_time));
if (HasUnitState(UNIT_STATE_MELEE_ATTACKING) && !HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_CHARGING))
{
if (Unit* victim = GetVictim())
{
// default combat reach 10
/// @todo add weapon, skill check
if (isAttackReady(BASE_ATTACK))
{
if (!IsWithinMeleeRange(victim))
{
setAttackTimer(BASE_ATTACK, 100);
if (m_swingErrorMsg != 1) // send single time (client auto repeat)
{
SendAttackSwingNotInRange();
m_swingErrorMsg = 1;
}
}
//120 degrees of radiant range, if player is not in boundary radius
else if (!IsWithinBoundaryRadius(victim) && !HasInArc(2 * float(M_PI) / 3, victim))
{
setAttackTimer(BASE_ATTACK, 100);
if (m_swingErrorMsg != 2) // send single time (client auto repeat)
{
SendAttackSwingBadFacingAttack();
m_swingErrorMsg = 2;
}
}
else
{
m_swingErrorMsg = 0; // reset swing error state
// prevent base and off attack in same time, delay attack at 0.2 sec
if (haveOffhandWeapon())
if (getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
// do attack
AttackerStateUpdate(victim, BASE_ATTACK);
resetAttackTimer(BASE_ATTACK);
}
}
if (!IsInFeralForm() && haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
{
if (!IsWithinMeleeRange(victim))
setAttackTimer(OFF_ATTACK, 100);
else if (!IsWithinBoundaryRadius(victim) && !HasInArc(2 * float(M_PI) / 3, victim))
{
setAttackTimer(BASE_ATTACK, 100);
}
else
{
// prevent base and off attack in same time, delay attack at 0.2 sec
if (getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
// do attack
AttackerStateUpdate(victim, OFF_ATTACK);
resetAttackTimer(OFF_ATTACK);
}
}
/*Unit* owner = victim->GetOwner();
Unit* u = owner ? owner : victim;
if (u->IsPvP() && (!duel || duel->opponent != u))
{
UpdatePvP(true);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive);
}*/
}
}
DoMeleeAttackIfReady();
if (HasPlayerFlag(PLAYER_FLAGS_RESTING))
_restMgr->Update(now);
@@ -21308,29 +21235,17 @@ void Player::SavePositionInDB(WorldLocation const& loc, uint16 zoneId, ObjectGui
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void Player::SendAttackSwingCantAttack() const
{
SendDirectMessage(WorldPackets::Combat::AttackSwingError(WorldPackets::Combat::AttackSwingError::CantAttack).Write());
}
void Player::SendAttackSwingCancelAttack() const
{
SendDirectMessage(WorldPackets::Combat::CancelCombat().Write());
}
void Player::SendAttackSwingDeadTarget() const
void Player::SetAttackSwingError(Optional<AttackSwingErr> err)
{
SendDirectMessage(WorldPackets::Combat::AttackSwingError(WorldPackets::Combat::AttackSwingError::DeadTarget).Write());
}
if (err && err != m_swingErrorMsg)
SendDirectMessage(WorldPackets::Combat::AttackSwingError(*err).Write());
void Player::SendAttackSwingNotInRange() const
{
SendDirectMessage(WorldPackets::Combat::AttackSwingError(WorldPackets::Combat::AttackSwingError::NotInRange).Write());
}
void Player::SendAttackSwingBadFacingAttack() const
{
SendDirectMessage(WorldPackets::Combat::AttackSwingError(WorldPackets::Combat::AttackSwingError::BadFacing).Write());
m_swingErrorMsg = err;
}
void Player::SendAutoRepeatCancel(Unit* target)
+2 -5
View File
@@ -2126,11 +2126,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void DestroyForPlayer(Player* target) const override;
// notifiers
void SendAttackSwingCantAttack() const;
void SendAttackSwingCancelAttack() const;
void SendAttackSwingDeadTarget() const;
void SendAttackSwingNotInRange() const;
void SendAttackSwingBadFacingAttack() const;
void SetAttackSwingError(Optional<AttackSwingErr> err);
void SendAutoRepeatCancel(Unit* target);
void SendExplorationExperience(uint32 Area, uint32 Experience) const;
@@ -3096,7 +3093,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool m_canBlock;
bool m_canTitanGrip;
uint32 m_titanGripPenaltySpellId;
uint8 m_swingErrorMsg;
Optional<AttackSwingErr> m_swingErrorMsg;
// Social
PlayerSocial* m_social;
+76 -20
View File
@@ -407,8 +407,8 @@ Unit::~Unit()
ASSERT(m_appliedAuras.empty());
ASSERT(m_ownedAuras.empty());
ASSERT(m_removedAuras.empty());
ASSERT(m_gameObj.empty());
ASSERT(m_dynObj.empty());
ASSERT(m_gameObj.empty());
ASSERT(m_areaTrigger.empty());
ASSERT(!m_unitMovedByMe || (m_unitMovedByMe == this));
ASSERT(!m_playerMovingMe || (m_playerMovingMe == this));
@@ -456,10 +456,10 @@ void Unit::Update(uint32 p_time)
{
if (uint32 base_att = getAttackTimer(BASE_ATTACK))
setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time));
if (uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time));
if (uint32 off_att = getAttackTimer(OFF_ATTACK))
setAttackTimer(OFF_ATTACK, (p_time >= off_att ? 0 : off_att - p_time));
if (uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time));
}
// update abilities available only for fraction of time
@@ -2087,12 +2087,15 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
}
}
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
void Unit::DoMeleeAttackIfReady()
{
if (HasUnitFlag(UNIT_FLAG_PACIFIED))
if (!HasUnitState(UNIT_STATE_MELEE_ATTACKING))
return;
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) && !extra)
if (HasUnitState(UNIT_STATE_CHARGING))
return;
if (IsCreature() && !ToCreature()->CanMelee())
return;
if (HasUnitState(UNIT_STATE_CASTING))
@@ -2102,6 +2105,69 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
return;
}
Unit* victim = GetVictim();
if (!victim)
return;
auto getAutoAttackError = [&]() -> Optional<AttackSwingErr>
{
if (!IsWithinMeleeRange(victim))
return AttackSwingErr::NotInRange;
//120 degrees of radiant range, if player is not in boundary radius
if (!IsWithinBoundaryRadius(victim) && !HasInArc(2 * float(M_PI) / 3, victim))
return AttackSwingErr::BadFacing;
return {};
};
if (isAttackReady(BASE_ATTACK))
{
Optional<AttackSwingErr> autoAttackError = getAutoAttackError();
if (!autoAttackError)
{
// prevent base and off attack in same time, delay attack at 0.2 sec
if (haveOffhandWeapon())
if (getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
// do attack
AttackerStateUpdate(victim, BASE_ATTACK);
resetAttackTimer(BASE_ATTACK);
}
else
setAttackTimer(BASE_ATTACK, 100);
if (Player* attackerPlayer = ToPlayer())
attackerPlayer->SetAttackSwingError(autoAttackError);
}
if (!IsInFeralForm() && haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
{
Optional<AttackSwingErr> autoAttackError = getAutoAttackError();
if (!autoAttackError)
{
// prevent base and off attack in same time, delay attack at 0.2 sec
if (getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
// do attack
AttackerStateUpdate(victim, OFF_ATTACK);
resetAttackTimer(OFF_ATTACK);
}
else
setAttackTimer(OFF_ATTACK, 100);
}
}
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
{
if (HasUnitFlag(UNIT_FLAG_PACIFIED))
return;
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) && !extra)
return;
if (HasAuraType(SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES))
return;
@@ -5070,7 +5136,7 @@ void Unit::_RegisterDynObject(DynamicObject* dynObj)
void Unit::_UnregisterDynObject(DynamicObject* dynObj)
{
m_dynObj.remove(dynObj);
std::erase(m_dynObj, dynObj);
if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustUnregisteredDynObject(dynObj);
}
@@ -5093,8 +5159,6 @@ std::vector<DynamicObject*> Unit::GetDynObjects(uint32 spellId) const
void Unit::RemoveDynObject(uint32 spellId)
{
if (m_dynObj.empty())
return;
for (DynObjectList::iterator i = m_dynObj.begin(); i != m_dynObj.end();)
{
DynamicObject* dynObj = *i;
@@ -5111,7 +5175,7 @@ void Unit::RemoveDynObject(uint32 spellId)
void Unit::RemoveAllDynObjects()
{
while (!m_dynObj.empty())
m_dynObj.front()->Remove();
m_dynObj.back()->Remove();
}
GameObject* Unit::GetGameObject(uint32 spellId) const
@@ -5598,14 +5662,8 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
Creature* creature = ToCreature();
// creatures cannot attack while evading
if (creature)
{
if (creature->IsInEvadeMode())
return false;
if (!creature->CanMelee())
meleeAttack = false;
}
if (creature && creature->IsInEvadeMode())
return false;
// nobody can attack GM in GM-mode
if (victim->GetTypeId() == TYPEID_PLAYER)
@@ -11022,7 +11080,6 @@ void Unit::SetControlled(bool apply, UnitState state)
case UNIT_STATE_CONFUSED:
if (!HasUnitState(UNIT_STATE_STUNNED))
{
ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
SendMeleeAttackStop();
// SendAutoRepeatCancel ?
SetConfused(true);
@@ -11031,7 +11088,6 @@ void Unit::SetControlled(bool apply, UnitState state)
case UNIT_STATE_FLEEING:
if (!HasUnitState(UNIT_STATE_STUNNED | UNIT_STATE_CONFUSED))
{
ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
SendMeleeAttackStop();
// SendAutoRepeatCancel ?
SetFeared(true);
+3 -2
View File
@@ -1053,7 +1053,8 @@ class TC_GAME_API Unit : public WorldObject
void TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProcContainer& procAuras);
void HandleEmoteCommand(Emote emoteId, Player* target = nullptr, Trinity::IteratorPair<int32 const*> spellVisualKitIds = {}, int32 sequenceVariation = 0);
void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false);
void DoMeleeAttackIfReady();
void AttackerStateUpdate(Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false);
void CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK);
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);
@@ -1957,7 +1958,7 @@ class TC_GAME_API Unit : public WorldObject
int32 m_procDeep; // tracked for proc system correctness (what spells should proc what)
int32 m_procChainLength; // tracked to protect against infinite proc loops (hard limit, will disallow procs even if they should happen)
typedef std::list<DynamicObject*> DynObjectList;
typedef std::vector<DynamicObject*> DynObjectList;
DynObjectList m_dynObj;
typedef std::list<GameObject*> GameObjectList;
@@ -473,6 +473,14 @@ enum HitInfo
HITINFO_FAKE_DAMAGE = 0x01000000 // enables damage animation even if no damage done, set only if no damage
};
enum class AttackSwingErr : uint8
{
NotInRange = 0,
BadFacing = 1,
CantAttack = 2,
DeadTarget = 3
};
#define MAX_DECLINED_NAME_CASES 5
struct TC_GAME_API DeclinedName
@@ -96,7 +96,7 @@ WorldPacket const* WorldPackets::Combat::AIReaction::Write()
WorldPacket const* WorldPackets::Combat::AttackSwingError::Write()
{
_worldPacket.WriteBits(Reason, 3);
_worldPacket.WriteBits(AsUnderlyingType(Reason), 3);
_worldPacket.FlushBits();
return &_worldPacket;
}
@@ -20,6 +20,7 @@
#include "Packet.h"
#include "ObjectGuid.h"
#include "UnitDefines.h"
class Unit;
enum Powers : int8;
@@ -41,20 +42,12 @@ namespace WorldPackets
class AttackSwingError final : public ServerPacket
{
public:
enum AttackSwingErr : uint8
{
NotInRange = 0,
BadFacing = 1,
CantAttack = 2,
DeadTarget = 3
};
AttackSwingError() : ServerPacket(SMSG_ATTACK_SWING_ERROR, 4) { }
AttackSwingError(AttackSwingErr reason) : ServerPacket(SMSG_ATTACK_SWING_ERROR, 4), Reason(reason) { }
WorldPacket const* Write() override;
AttackSwingErr Reason = CantAttack;
AttackSwingErr Reason = AttackSwingErr::CantAttack;
};
class AttackStop final : public ClientPacket
@@ -434,9 +434,7 @@ struct boss_garothi_worldbreaker : public BossAI
return;
}
if (me->GetVictim() && me->GetVictim()->IsWithinMeleeRange(me))
DoMeleeAttackIfReady();
else
if (!me->GetVictim() || !me->GetVictim()->IsWithinMeleeRange(me))
DoSpellAttackIfReady(SPELL_CARNAGE);
}
private:
@@ -291,8 +291,6 @@ struct boss_guarm : public BossAI
default:
break;
}
DoMeleeAttackIfReady();
}
void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
@@ -620,8 +620,6 @@ struct npc_illidari_fighting_invasion_begins : public ScriptedAI
default:
break;
}
DoMeleeAttackIfReady();
}
private:
@@ -1110,8 +1108,6 @@ struct npc_inquisitor_baleful_molten_shore : public ScriptedAI
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -205,8 +205,6 @@ struct boss_leymor : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -284,8 +282,6 @@ struct npc_arcane_tender : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
@@ -227,7 +227,6 @@ struct boss_telash_greywing : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
void DoAction(int32 param) override
@@ -124,8 +124,6 @@ struct npc_av_marshal_or_warmaster : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -169,8 +169,6 @@ struct boss_balinda : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -125,8 +125,6 @@ struct boss_drekthar : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -126,8 +126,6 @@ struct boss_galvangar : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -85,10 +85,7 @@ struct boss_vanndar : public ScriptedAI
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -245,8 +245,6 @@ class boss_alizabal : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -140,8 +140,6 @@ class boss_occuthar : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -111,8 +111,6 @@ class boss_pit_lord_argaloth : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -202,8 +202,6 @@ public: npc_twilight_flame_caller() : CreatureScript("npc_twilight_flame_caller"
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -313,8 +311,6 @@ class npc_twilight_torturer : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -414,8 +410,6 @@ class npc_twilight_sadist : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -489,7 +483,6 @@ class npc_mad_prisoner : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -559,8 +552,6 @@ class npc_crazed_mage : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -653,8 +644,6 @@ class npc_raz_the_crazed : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -95,8 +95,6 @@ class boss_ascendant_lord_obsidius : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -102,8 +102,6 @@ class boss_beauty : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -109,8 +109,6 @@ class boss_corla : public CreatureScript
}
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -97,8 +97,6 @@ class boss_karsh_steelbender : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -122,8 +122,6 @@ class boss_romogg_bonecrusher : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -425,8 +425,6 @@ public:
DoCastVictim(SPELL_MIGHTYBLOW);
MightyBlow_Timer = 10000;
} else MightyBlow_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -76,8 +76,6 @@ class boss_ambassador_flamelash : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -279,8 +279,6 @@ struct boss_coren_direbrew : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -326,10 +324,7 @@ struct npc_coren_direbrew_sisters : public ScriptedAI
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -105,8 +105,6 @@ class boss_emperor_dagran_thaurissan : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -117,8 +117,6 @@ class boss_general_angerforge : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -86,8 +86,6 @@ class boss_high_interrogator_gerstahn : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -86,8 +86,6 @@ class boss_magmus : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
@@ -225,8 +225,6 @@ class boss_doomrel : public CreatureScript
break;
}
}
DoMeleeAttackIfReady();
}
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
@@ -93,7 +93,6 @@ struct boss_drakkisath : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -95,7 +95,6 @@ struct boss_gizrul_the_slavener : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -168,7 +168,6 @@ struct boss_gyth : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -99,7 +99,6 @@ struct boss_halycon : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
bool Summoned;
@@ -81,7 +81,6 @@ struct boss_highlord_omokk : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -124,8 +124,6 @@ struct boss_lord_valthalak : public BossAI
frenzy15 = true;
}
}
DoMeleeAttackIfReady();
}
private:
bool frenzy40;
@@ -86,7 +86,6 @@ struct boss_mother_smolderweb : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -126,7 +126,6 @@ struct boss_overlord_wyrmthalak : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -273,7 +273,6 @@ struct boss_pyroguard_emberseer : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -344,8 +343,6 @@ struct npc_blackhand_incarcerator : public ScriptedAI
break;
}
}
DoMeleeAttackIfReady();
}
private:
@@ -81,7 +81,6 @@ struct quartermaster_zigris : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -438,7 +438,6 @@ struct boss_rend_blackhand : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -88,7 +88,6 @@ struct boss_shadow_hunter_voshgajin : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -97,7 +97,6 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
};
@@ -90,7 +90,6 @@ struct boss_urok_doomhowl : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -107,7 +107,6 @@ struct boss_warmaster_voone : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -119,8 +119,6 @@ struct boss_broodlord : public BossAI
break;
}
}
DoMeleeAttackIfReady();
}
};
@@ -171,9 +171,7 @@ struct boss_chromaggus : public BossAI
Breath1_Spell = SPELL_FROSTBURN;
Breath2_Spell = SPELL_IGNITEFLESH;
break;
};
EnterEvadeMode();
}
}
void Initialize()
@@ -275,8 +273,6 @@ struct boss_chromaggus : public BossAI
DoCast(me, SPELL_ENRAGE);
Enraged = true;
}
DoMeleeAttackIfReady();
}
private:
@@ -77,8 +77,6 @@ struct boss_ebonroc : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -79,8 +79,6 @@ struct boss_firemaw : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -85,8 +85,6 @@ struct boss_flamegor : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -568,8 +568,6 @@ struct boss_nefarian : public BossAI
Phase3 = true;
Talk(SAY_RAISE_SKELETONS);
}
DoMeleeAttackIfReady();
}
private:
@@ -152,7 +152,6 @@ struct boss_razorgore : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -213,8 +213,6 @@ struct boss_vaelastrasz : public BossAI
Talk(SAY_HALFLIFE);
HasYelled = true;
}
DoMeleeAttackIfReady();
}
bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
@@ -107,8 +107,6 @@ struct boss_baron_geddon : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -85,8 +85,6 @@ struct boss_garr : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -145,10 +143,7 @@ struct npc_firesworn : public ScriptedAI
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -89,8 +89,6 @@ struct boss_gehennas : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -107,8 +107,6 @@ struct boss_golemagg : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -154,10 +152,7 @@ struct npc_core_rager : public ScriptedAI
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -87,8 +87,6 @@ struct boss_lucifron : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -101,8 +101,6 @@ struct boss_magmadar : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -145,8 +145,6 @@ struct boss_majordomo : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
else
{
@@ -292,8 +292,6 @@ struct boss_ragnaros : public BossAI
break;
}
}
DoMeleeAttackIfReady();
}
}
@@ -317,14 +315,6 @@ struct npc_son_of_flame : public ScriptedAI //didnt work correctly in EAI for me
instance->SetData(DATA_RAGNAROS_ADDS, 1);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* instance;
};
@@ -104,8 +104,6 @@ struct boss_shazzrah : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -119,8 +119,6 @@ struct boss_sulfuron : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -184,8 +182,6 @@ struct npc_flamewaker_priest : public ScriptedAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -488,10 +488,7 @@ public:
} else uiTimer -= uiDiff;
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
UpdateVictim();
}
void JustSummoned(Creature* summon) override
@@ -530,14 +527,6 @@ public:
creature->AI()->SetData(2, 1);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
if (!me->IsSummon())
@@ -116,8 +116,6 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
@@ -219,10 +219,7 @@ public:
if (!UpdateVictim() && _phase != PHASE_NONE)
return;
scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
scheduler.Update(diff);
}
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
@@ -370,10 +367,7 @@ public:
if (!UpdateVictim() || _phase == PHASE_MOUNTED)
return;
scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
scheduler.Update(diff);
}
private:
@@ -287,6 +287,7 @@ public:
if (Vanish_Timer <= diff)
{
DoCast(me, SPELL_VANISH);
me->SetCanMelee(false);
InVanish = true;
Vanish_Timer = 30000;
Wait_Timer = 5000;
@@ -316,11 +317,9 @@ public:
target->CastSpell(target, SPELL_GARROTE, true);
InVanish = false;
me->SetCanMelee(true);
} else Wait_Timer -= diff;
}
if (!InVanish)
DoMeleeAttackIfReady();
}
};
};
@@ -371,8 +370,6 @@ struct boss_moroes_guestAI : public ScriptedAI
{
if (instance->GetBossState(DATA_MOROES) != IN_PROGRESS)
EnterEvadeMode();
DoMeleeAttackIfReady();
}
};
@@ -345,8 +345,6 @@ public:
}
} else PhaseTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
};
@@ -370,8 +370,6 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -550,8 +550,6 @@ public:
EnfeebleResetTimer = 9000;
} else EnfeebleTimer -= diff;
}
DoMeleeAttackIfReady();
}
void Cleanup(Creature* infernal, InfernalPoint *point)
@@ -173,6 +173,7 @@ public:
void Reset() override
{
Initialize();
me->SetCanMelee(true);
// Not in progress
instance->SetBossState(DATA_ARAN, NOT_STARTED);
@@ -488,8 +489,7 @@ public:
} else FlameWreathCheckTime -= diff;
}
if (ArcaneCooldown && FireCooldown && FrostCooldown)
DoMeleeAttackIfReady();
me->SetCanMelee(ArcaneCooldown && FireCooldown && FrostCooldown);
}
void DamageTaken(Unit* /*pAttacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
@@ -185,10 +185,7 @@ public:
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -303,10 +300,7 @@ public:
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
_scheduler.Update(diff);
}
private:
@@ -229,8 +229,6 @@ public:
SummonTito();
else SummonTitoTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
};
@@ -291,8 +289,6 @@ public:
DoCastVictim(SPELL_YIPPING);
YipTimer = 10000;
} else YipTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -423,8 +419,6 @@ public:
DoCast(target, SPELL_BRAIN_WIPE);
BrainWipeTimer = 20000;
} else BrainWipeTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -538,8 +532,6 @@ public:
RustTimer = 6000;
} else RustTimer -= diff;
}
DoMeleeAttackIfReady();
}
};
};
@@ -652,8 +644,6 @@ public:
DoCastVictim(SPELL_FRIGHTENED_SCREAM);
ScreamTimer = urand(20000, 30000);
} else ScreamTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -737,8 +727,6 @@ public:
DoCastVictim(SPELL_CHAIN_LIGHTNING);
ChainLightningTimer = 15000;
} else ChainLightningTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -914,8 +902,6 @@ public:
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
if (ChaseTimer <= diff)
{
if (!IsChasing)
@@ -1358,8 +1344,6 @@ public:
DoCastVictim(SPELL_POISON_THRUST);
PoisonThrustTimer = urand(10000, 20000);
} else PoisonThrustTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -1480,8 +1464,6 @@ void boss_julianne::boss_julianneAI::UpdateAI(uint32 diff)
EternalAffectionTimer = urand(45000, 60000);
} else EternalAffectionTimer -= diff;
DoMeleeAttackIfReady();
}
void boss_julianne::boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/)
@@ -474,8 +474,6 @@ struct npc_felblood_kaelthas_phoenix : public ScriptedAI
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
@@ -334,8 +334,6 @@ public:
SWPainTimer = 10000;
} else SWPainTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -508,6 +506,7 @@ public:
{
Initialize();
me->SetVisible(true);
me->SetCanMelee(true);
boss_priestess_lackey_commonAI::Reset();
}
@@ -531,6 +530,7 @@ public:
AddThreat(unit, 1000.0f);
InVanish = true;
me->SetCanMelee(false);
Vanish_Timer = 30000;
Wait_Timer = 10000;
} else Vanish_Timer -= diff;
@@ -543,6 +543,7 @@ public:
DoCastVictim(SPELL_KIDNEY_SHOT, true);
me->SetVisible(true); // ...? Hacklike
InVanish = false;
me->SetCanMelee(true);
} else Wait_Timer -= diff;
}
@@ -563,9 +564,6 @@ public:
DoCastVictim(SPELL_EVISCERATE);
Eviscerate_Timer = 4000;
} else Eviscerate_Timer -= diff;
if (!InVanish)
DoMeleeAttackIfReady();
}
};
};
@@ -668,8 +666,6 @@ public:
Fear_Timer = 10000;
} else Fear_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -732,8 +728,6 @@ public:
DoCastVictim(SPELL_SNAP_KICK);
Snap_Kick_Timer = 4500;
} else Snap_Kick_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -865,8 +859,6 @@ public:
Blink_Timer = 8000;
} else Blink_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -987,8 +979,6 @@ public:
DoCastVictim(SPELL_FRIGHTENING_SHOUT);
Frightening_Shout_Timer = 18000;
} else Frightening_Shout_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -1088,8 +1078,6 @@ public:
Freezing_Trap_Timer = 15000;
}
} else Freezing_Trap_Timer -= diff;
DoMeleeAttackIfReady();
}
else
{
@@ -1202,8 +1190,6 @@ public:
DoCast(me, SPELL_LESSER_HEALING_WAVE);
Healing_Wave_Timer = 5000;
} else Healing_Wave_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -1304,8 +1290,6 @@ public:
DoCast(me, SPELL_HIGH_EXPLOSIVE_SHEEP);
High_Explosive_Sheep_Timer = 65000;
} else High_Explosive_Sheep_Timer -= diff;
DoMeleeAttackIfReady();
}
};
};
@@ -239,8 +239,6 @@ class boss_selin_fireheart : public CreatureScript
events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, 20s, 25s, 0, PHASE_NORMAL);
}
}
DoMeleeAttackIfReady();
}
private:
@@ -167,8 +167,6 @@ class boss_vexallus : public CreatureScript
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
@@ -282,8 +282,6 @@ public:
break;
}
}
DoMeleeAttackIfReady();
break;
default:
break;
@@ -1069,31 +1067,22 @@ struct npc_scarlet_ghoul : public ScriptedAI
Player* plrOwner = owner->ToPlayer();
if (plrOwner && plrOwner->IsInCombat())
{
if (plrOwner->getAttackerForHelper() && plrOwner->getAttackerForHelper()->GetEntry() == NPC_GHOSTS)
AttackStart(plrOwner->getAttackerForHelper());
Unit* newTarget = plrOwner->getAttackerForHelper();
if (newTarget && newTarget->GetEntry() == NPC_GHOSTS)
AttackStart(newTarget);
else
FindMinions(owner);
}
}
}
if (!UpdateVictim() || !me->GetVictim())
if (!UpdateVictim())
return;
}
//ScriptedAI::UpdateAI(diff);
//Check if we have a current target
if (me->EnsureVictim()->GetEntry() == NPC_GHOSTS)
{
if (me->isAttackReady())
{
//If we are within range melee the target
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->AttackerStateUpdate(me->GetVictim());
me->resetAttackTimer();
}
}
}
bool CanAIAttack(Unit const* target) const override
{
return target->GetEntry() == NPC_GHOSTS;
}
};
@@ -1259,8 +1248,6 @@ struct npc_hearthglen_crusader : public ScriptedAI
if (!me->IsWithinCombatRange(me->GetVictim(), _minimumRange))
DoSpellAttackIfReady(me->m_spells[0]);
else
DoMeleeAttackIfReady();
}
void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
@@ -416,8 +416,6 @@ public:
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
};
@@ -1465,8 +1465,6 @@ public:
SetHoldState(false);
} else uiFight_duration -= diff;
DoMeleeAttackIfReady();
}
}
@@ -107,8 +107,6 @@ struct boss_arcanist_doan : public BossAI
DoCastSelf(SPELL_ARCANE_BUBBLE);
DoCastAOE(SPELL_DETONATION);
}
DoMeleeAttackIfReady();
}
private:
@@ -96,8 +96,6 @@ struct boss_azshir_the_sleepless : public BossAI
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:

Some files were not shown because too many files have changed in this diff Show More