Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
UnitCombatState.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battlefield.h"
7#include "BattlefieldMgr.h"
8#include "Battleground.h"
9#include "CellImpl.h"
10#include "Common.h"
11#include "ConditionMgr.h"
12#include "Creature.h"
13#include "CreatureAI.h"
14#include "CreatureAIImpl.h"
15#include "CreatureGroups.h"
16#include "Formulas.h"
17#include "GridNotifiersImpl.h"
18#include "Group.h"
19#include "InstanceSaveMgr.h"
20#include "InstanceScript.h"
21#include "Log.h"
22#include "MapManager.h"
23#include "MovementStructures.h"
24#include "MoveSpline.h"
25#include "ObjectAccessor.h"
26#include "ObjectMgr.h"
27#include "Opcodes.h"
28#include "OutdoorPvP.h"
29#include "PassiveAI.h"
30#include "Pet.h"
31#include "PetAI.h"
32#include "Player.h"
33#include "QuestDef.h"
34#include "ReputationMgr.h"
35#include "Spell.h"
36#include "SpellAuraEffects.h"
37#include "SpellAuras.h"
38#include "SpellInfo.h"
39#include "SpellMgr.h"
40#include "TemporarySummon.h"
41#include "Totem.h"
42#include "Transport.h"
43#include "Unit.h"
44#include "UpdateFieldFlags.h"
45#include "Util.h"
46#include "Vehicle.h"
47#include "World.h"
48#include "WorldPacket.h"
49#include "WorldSession.h"
50
51#include <math.h>
52
53void Unit::_addAttacker(Unit* pAttacker)
54{
55 m_attackers.insert(pAttacker);
56}
57
59{
60 m_attackers.erase(pAttacker);
61}
62
63Unit* Unit::getAttackerForHelper() const // If someone wants to help, who to give them
64{
65 if (GetVictim() != NULL)
66 return GetVictim();
67
68 if (!m_attackers.empty())
69 return *(m_attackers.begin());
70
71 return NULL;
72}
73
74bool Unit::Attack(Unit* victim, bool meleeAttack)
75{
76 if (!victim || victim == this)
77 return false;
78
79 // dead units can neither attack nor be attacked
80 if (!IsAlive() || !victim->IsInWorld() || !victim->IsAlive())
81 return false;
82
83 // player cannot attack in mount state
85 return false;
86
88 return false;
89
90 // nobody can attack GM in GM-mode
91 if (victim->GetTypeId() == TypeID::TYPEID_PLAYER)
92 {
93 if (victim->ToPlayer()->IsGameMaster())
94 return false;
95 }
96 else
97 {
98 if (victim->ToCreature()->IsInEvadeMode())
99 return false;
100 }
101
102 // remove SPELL_AURA_MOD_UNATTACKABLE at attack (in case non-interruptible spells stun aura applied also that not let attack)
105
106 if (m_attacking)
107 {
108 if (m_attacking == victim)
109 {
110 // switch to melee attack from ranged/magic
111 if (meleeAttack)
112 {
114 {
116 SendMeleeAttackStart(victim);
117 return true;
118 }
119 }
121 {
123 SendMeleeAttackStop(victim);
124 return true;
125 }
126 return false;
127 }
128
129 // switch target
131 if (!meleeAttack)
133 }
134
135 if (m_attacking)
136 m_attacking->_removeAttacker(this);
137
138 m_attacking = victim;
139 m_attacking->_addAttacker(this);
140
141 // Set our target
142 SetTarget(victim->GetGUID());
143
144 if (meleeAttack)
146
147 // set position before any AI calls/assistance
148 //if (GetTypeId() == TYPEID_UNIT)
149 // ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
150
152 {
153 // should not let player enter combat by right clicking target - doesn't helps
154 SetInCombatWith(victim);
155 if (victim->GetTypeId() == TypeID::TYPEID_PLAYER)
156 victim->SetInCombatWith(this);
157 AddThreat(victim, 0.0f);
158
161 }
162
163 // delay offhand weapon attack to next attack time
164 if (haveOffhandWeapon())
166
167 if (meleeAttack)
168 SendMeleeAttackStart(victim);
169
170 // Let the pet know we've started attacking someting. Handles melee attacks only
171 // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
172 if (this->GetTypeId() == TypeID::TYPEID_PLAYER)
173 {
174 Pet* playerPet = this->ToPlayer()->GetPet();
175
176 if (playerPet && playerPet->IsAlive())
177 playerPet->AI()->OwnerAttacked(victim);
178 }
179
180 return true;
181}
182
184{
185 if (!m_attacking)
186 return false;
187
188 Unit* victim = m_attacking;
189
190 m_attacking->_removeAttacker(this);
191 m_attacking = NULL;
192
193 // Clear our target
194 SetTarget(0);
195
197
199
200 // reset only at real combat stop
201 if (Creature* creature = ToCreature())
202 {
203 creature->SetNoCallAssistance(false);
204
205 if (creature->HasSearchedAssistance())
206 {
207 creature->SetNoSearchAssistance(false);
208 UpdateSpeed(MOVE_RUN, false);
209 }
210 }
211
212 SendMeleeAttackStop(victim);
213
214 return true;
215}
216
217void Unit::CombatStop(bool includingCast)
218{
219 if (includingCast && IsNonMeleeSpellCasted(false))
221
222 AttackStop();
225 ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
227}
228
229void Unit::CombatStopWithPets(bool includingCast)
230{
231 CombatStop(includingCast);
232
233 for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
234 (*itr)->CombatStop(includingCast);
235}
236
238{
240 return true;
241
242 for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
243 if ((*itr)->isAttackingPlayer())
244 return true;
245
246 for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
247 if (m_SummonSlot[i])
248 if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i]))
249 if (summon->isAttackingPlayer())
250 return true;
251
252 return false;
253}
254
256{
257 while (!m_attackers.empty())
258 {
259 AttackerSet::iterator iter = m_attackers.begin();
260 if (!(*iter)->AttackStop())
261 {
262 SF_LOG_ERROR("entities.unit", "WORLD: Unit has an attacker that isn't attacking it!");
263 m_attackers.erase(iter);
264 }
265 }
266}
267
269{
270 Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf();
271 if (eOwner->IsPvP())
272 {
273 SetInCombatState(true, enemy);
274 return;
275 }
276
277 // check for duel
278 if (eOwner->GetTypeId() == TypeID::TYPEID_PLAYER && eOwner->ToPlayer()->duel)
279 {
280 Unit const* myOwner = GetCharmerOrOwnerOrSelf();
281 if (((Player const*)eOwner)->duel->opponent == myOwner)
282 {
283 SetInCombatState(true, enemy);
284 return;
285 }
286 }
287 SetInCombatState(false, enemy);
288}
289
290void Unit::CombatStart(Unit* target, bool initialAggro)
291{
292 if (initialAggro)
293 {
294 if (!target->IsStandState())
296
297 if (!target->IsInCombat() && target->GetTypeId() != TypeID::TYPEID_PLAYER
298 && !target->ToCreature()->HasReactState(REACT_PASSIVE) && target->ToCreature()->IsAIEnabled)
299 {
300 if (target->IsPet())
301 target->ToCreature()->AI()->AttackedBy(this); // PetAI has special handler before AttackStart()
302 else
303 target->ToCreature()->AI()->AttackStart(this);
304 }
305
306 SetInCombatWith(target);
307 target->SetInCombatWith(this);
308 }
309 Unit* who = target->GetCharmerOrOwnerOrSelf();
310 if (who->GetTypeId() == TypeID::TYPEID_PLAYER)
312
314 if (me && who->IsPvP()
315 && (who->GetTypeId() != TypeID::TYPEID_PLAYER
316 || !me->duel || me->duel->opponent != who))
317 {
318 me->UpdatePvP(true);
320 }
321}
322
323void Unit::SetInCombatState(bool PvP, Unit* enemy)
324{
325 // only alive units can be in combat
326 if (!IsAlive())
327 return;
328
329 if (PvP)
330 m_CombatTimer = 5000;
331
332 // Pulling a creature into combat must override evade (e.g. wandering mobs hit at range).
335
336 if (IsInCombat())
337 return;
338
340
341 if (Creature* creature = ToCreature())
342 {
343 // Set home position at place of engaging combat so leash checks use the pull location.
344 if ((IsAIEnabled && creature->AI()->IsEscorted()) ||
345 GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE ||
346 GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE ||
347 GetMotionMaster()->GetCurrentMovementGeneratorType() == RANDOM_MOTION_TYPE)
348 creature->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
349
350 if (enemy)
351 {
352 if (IsAIEnabled)
353 {
354 creature->AI()->EnterCombat(enemy);
355 RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // unit has engaged in combat, remove immunity so players can fight back
356 }
357 if (creature->GetFormation())
358 creature->GetFormation()->MemberAttackStart(creature, enemy);
359 }
360
361 if (IsPet())
362 {
363 UpdateSpeed(MOVE_RUN, true);
364 UpdateSpeed(MOVE_SWIM, true);
366 }
367
368 if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT))
369 Dismount();
370 }
371
372 for (Unit::ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
373 {
374 (*itr)->SetInCombatState(PvP, enemy);
376 }
377
378 if (Player* player = ToPlayer())
379 {
380 if (player->HasAuraType(SPELL_AURA_ENABLE_WORGER_ALTERED_FORM) && !player->HasAuraType(SPELL_AURA_WORGEN_ALTERED_FORM))
381 player->CastSpell(player, 97709, true);
382 }
383}
384
386{
387 m_CombatTimer = 0;
389
390 // Player's state will be cleared in Player::UpdateContestedPvP
391 if (Creature* creature = ToCreature())
392 {
393 if (creature->GetCreatureTemplate() && creature->GetCreatureTemplate()->unit_flags & UNIT_FLAG_IMMUNE_TO_PC)
394 SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // set immunity state to the one from db on evade
395
398 SetUInt32Value(OBJECT_FIELD_DYNAMIC_FLAGS, creature->GetCreatureTemplate()->dynamicflags);
399
400 if (creature->IsPet())
401 {
402 if (Unit* owner = GetOwner())
403 for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
404 if (owner->GetSpeedRate(UnitMoveType(i)) > GetSpeedRate(UnitMoveType(i)))
405 SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
406 }
407 else if (!IsCharmed())
408 return;
409 }
410 else
412
414}
415
416void Unit::SetContestedPvP(Player* attackedPlayer)
417{
419
420 if (!player || (attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer))))
421 return;
422
423 player->SetContestedPvPTimer(30000);
425 {
428 // call MoveInLineOfSight for nearby contested guards
430 }
432 {
434 // call MoveInLineOfSight for nearby contested guards
436 }
437}
std::uint8_t uint8
Definition Define.h:79
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ WAYPOINT_MOTION_TYPE
@ POINT_MOTION_TYPE
@ RANDOM_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ PLAYER_FLAGS_CONTESTED_PVP
Definition Player.h:545
@ UNIT_DYNFLAG_TAPPED
@ AI_REACTION_HOSTILE
@ CREATURE_TYPEFLAGS_MOUNTED_COMBAT
@ SPELL_AURA_WORGEN_ALTERED_FORM
@ SPELL_AURA_ENABLE_WORGER_ALTERED_FORM
@ SPELL_AURA_MOD_UNATTACKABLE
@ AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT
Definition Unit.h:64
#define MAX_MOVE_TYPE
Definition Unit.h:566
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
#define MAX_SUMMON_SLOT
Definition Unit.h:1344
@ CURRENT_MELEE_SPELL
Definition Unit.h:1108
@ UNIT_STATE_EVADE
Definition Unit.h:533
@ UNIT_STATE_ATTACK_PLAYER
Definition Unit.h:526
@ UNIT_STATE_MELEE_ATTACKING
Definition Unit.h:513
UnitMoveType
Definition Unit.h:554
@ MOVE_FLIGHT
Definition Unit.h:561
@ MOVE_SWIM
Definition Unit.h:558
@ MOVE_RUN
Definition Unit.h:556
@ REACT_PASSIVE
Definition Unit.h:1156
@ UNIT_FLAG_IN_COMBAT
Definition Unit.h:644
@ UNIT_FLAG_PACIFIED
Definition Unit.h:642
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ UNIT_FLAG_PET_IN_COMBAT
Definition Unit.h:636
@ UNIT_FIELD_FLAGS
@ OBJECT_FIELD_DYNAMIC_FLAGS
@ PLAYER_FIELD_PLAYER_FLAGS
virtual void OwnerAttacked(Unit *)
Definition CreatureAI.h:134
virtual void AttackedBy(Unit *)
Definition CreatureAI.h:111
bool HasReactState(ReactStates state) const
Definition Creature.h:462
void SendAIReaction(AiReaction reactionType)
void CallAssistance()
bool IsInEvadeMode() const
Definition Creature.h:478
CreatureAI * AI() const
Definition Creature.h:483
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
bool IsInWorld() const
Definition Object.h:114
TypeID GetTypeId() const
Definition Object.h:131
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
Creature * ToCreature()
Definition Object.h:207
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
Definition Pet.h:28
void SendAttackSwingCancelAttack()
Definition Player.cpp:15465
Pet * GetPet() const
Definition Player.cpp:15640
void UpdatePotionCooldown(Spell *spell=NULL)
Definition Player.cpp:17737
bool IsGameMaster() const
Definition Player.h:1369
void UpdatePvP(bool state, bool override=false)
Definition Player.cpp:17484
void SetContestedPvPTimer(uint32 newTime)
Definition Player.h:2246
DuelInfo * duel
Definition Player.h:2253
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
void ClearUnitState(uint32 f)
Definition Unit.h:1489
bool IsCharmed() const
Definition Unit.h:2136
Unit * GetOwner() const
Definition Unit.cpp:2339
void CombatStop(bool includingCast=false)
virtual void SetTarget(uint64)=0
void SendMeleeAttackStop(Unit *victim=NULL)
Definition Unit.cpp:647
uint32 m_CombatTimer
Definition Unit.h:2970
void UpdateObjectVisibility(bool forced=true) override
Definition Unit.cpp:7567
void SetContestedPvP(Player *attackedPlayer=NULL)
bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:1402
Unit * GetCharmerOrOwnerOrSelf() const
Definition Unit.cpp:2424
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
void AddThreat(Unit *victim, float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=NULL)
Definition Unit.cpp:4463
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Unit.cpp:2355
Unit * getAttackerForHelper() const
void SendMeleeAttackStart(Unit *victim)
Definition Unit.cpp:603
void _removeAttacker(Unit *pAttacker)
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:1433
bool IsPvP() const
Definition Unit.h:1716
bool haveOffhandWeapon() const
Definition Unit.cpp:350
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool IsPet() const
Definition Unit.h:1511
void _addAttacker(Unit *pAttacker)
void SetInCombatState(bool PvP, Unit *enemy=NULL)
void Dismount()
Definition Unit.cpp:3685
uint64 m_SummonSlot[MAX_SUMMON_SLOT]
Definition Unit.h:2374
bool isAttackingPlayer() const
void CombatStart(Unit *target, bool initialAggro=true)
bool IsAlive() const
Definition Unit.h:2032
bool IsStandState() const
Definition Unit.cpp:5896
ControlList m_Controlled
Definition Unit.h:2132
void AddUnitState(uint32 f)
Definition Unit.h:1481
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
bool Attack(Unit *victim, bool meleeAttack)
AttackerSet m_attackers
Definition Unit.h:2880
Unit * m_attacking
Definition Unit.h:2881
bool HasAuraType(AuraType auraType) const
bool IsMounted() const
Definition Unit.h:1742
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
float GetSpeedRate(UnitMoveType mtype) const
Definition Unit.h:2581
Unit * GetVictim() const
Definition Unit.h:1468
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition Unit.cpp:4318
bool IsAIEnabled
Definition Unit.h:2735
bool HasUnitState(const uint32 f) const
Definition Unit.h:1485
void resetAttackTimer(WeaponAttackType type=WeaponAttackType::BASE_ATTACK)
Definition Unit.cpp:436
Unit(bool isWorldObject)
Definition Unit.cpp:142
void RemoveAllAttackers()
void ClearInCombat()
void UpdateSpeed(UnitMoveType mtype, bool forced)
Definition Unit.cpp:4173
void SetStandState(uint8 state)
Definition Unit.cpp:5902
bool AttackStop()
void SetInCombatWith(Unit *enemy)
bool IsInCombat() const
Definition Unit.h:1896
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true)
Definition Unit.cpp:1365
void CombatStopWithPets(bool includingCast=false)
Map * GetMap() const
Definition Object.h:740
Player * opponent
Definition Player.h:459
float GetPositionZ() const
Definition Object.h:330
float GetOrientation() const
Definition Object.h:331
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329