TrinityCore
CombatManager.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITY_COMBATMANAGER_H
19#define TRINITY_COMBATMANAGER_H
20
21#include "Common.h"
22#include "ObjectGuid.h"
23#include <unordered_map>
24
25class Unit;
26
27/********************************************************************************************************************************************************\
28 * DEV DOCUMENTATION: COMBAT SYSTEM *
29 * (future devs: please keep this up-to-date if you change the system) *
30 * CombatManager maintains a list of dynamically allocated CombatReference entries. Each entry represents a combat state between two distinct units. *
31 * A unit is "in combat" iff it has one or more non-suppressed CombatReference entries in its CombatManager. No exceptions. *
32 * *
33 * A CombatReference object carries the following implicit guarantees by existing: *
34 * - Both CombatReference.first and CombatReference.second are valid Units, distinct, not nullptr and currently in the world. *
35 * - If the CombatReference was retrieved from the CombatManager of Unit* A, then exactly one of .first and .second is equal to A. *
36 * - Note: Use CombatReference::GetOther to quickly get the other unit for a given reference. *
37 * - Both .first and .second are currently in combat (IsInCombat will always be true) if either of the following hold: *
38 * - IsSuppressedFor returns false for the respective unit *
39 * *
40 * To end combat between two units, find their CombatReference and call EndCombat. *
41 * - Keep in mind that this modifies the CombatRefs maps on both ends, which may cause iterators to be invalidated. *
42 * *
43 * To put two units in combat with each other, call SetInCombatWith. Note that this is not guaranteed to succeed. *
44 * - The return value of SetInCombatWith is the new combat state between the units (identical to calling IsInCombatWith at that time). *
45 * *
46 * Note that (threat => combat) is a strong guarantee provided in conjunction with ThreatManager. Thus: *
47 * - Ending combat between two units will also delete any threat references that may exist between them. *
48 * - Adding threat will also create a combat reference between the units if one doesn't exist yet. *
49\********************************************************************************************************************************************************/
50
51// Please check Game/Combat/CombatManager.h for documentation on how this class works!
53{
54 Unit* const first;
55 Unit* const second;
56 bool const _isPvP;
57 Unit* GetOther(Unit const* me) const { return (first == me) ? second : first; }
58
59 void EndCombat();
60
61 // suppressed combat refs do not generate a combat state for one side of the relation
62 // (used by: vanish, feign death and launched out of combat but not yet landed spell missiles)
63 void SuppressFor(Unit* who);
64 bool IsSuppressedFor(Unit const* who) const { return (who == first) ? _suppressFirst : _suppressSecond; }
65
68
69protected:
70 CombatReference(Unit* a, Unit* b, bool pvp = false) : first(a), second(b), _isPvP(pvp) { }
71
72 void Refresh();
73 void Suppress(Unit* who) { (who == first ? _suppressFirst : _suppressSecond) = true; }
74
75 bool _suppressFirst = false;
76 bool _suppressSecond = false;
77
78 friend class CombatManager;
79};
80
81// Please check Game/Combat/CombatManager.h for documentation on how this class works!
83{
84 static const uint32 PVP_COMBAT_TIMEOUT = 5 * IN_MILLISECONDS;
85
86private:
87 PvPCombatReference(Unit* first, Unit* second) : CombatReference(first, second, true) { }
88
89 bool Update(uint32 tdiff);
90 void RefreshTimer();
91
92 uint32 _combatTimer = PVP_COMBAT_TIMEOUT;
93
94 friend class CombatManager;
95};
96
97// please check Game/Combat/CombatManager.h for documentation on how this class works!
99{
100 public:
101 static bool CanBeginCombat(Unit const* a, Unit const* b);
102
103 CombatManager(Unit* owner) : _owner(owner) { }
105 void Update(uint32 tdiff); // called from Unit::Update
106
107 Unit* GetOwner() const { return _owner; }
108 bool HasCombat() const { return HasPvECombat() || HasPvPCombat(); }
109 bool HasPvECombat() const;
110 bool HasPvECombatWithPlayers() const;
111 std::unordered_map<ObjectGuid, CombatReference*> const& GetPvECombatRefs() const { return _pveRefs; }
112 bool HasPvPCombat() const;
113 std::unordered_map<ObjectGuid, PvPCombatReference*> const& GetPvPCombatRefs() const { return _pvpRefs; }
114 // If the Unit is in combat, returns an arbitrary Unit that it's in combat with. Otherwise, returns nullptr.
115 Unit* GetAnyTarget() const;
116
117 // return value is the same as calling IsInCombatWith immediately after this returns
118 bool SetInCombatWith(Unit* who, bool addSecondUnitSuppressed = false);
119 bool IsInCombatWith(ObjectGuid const& who) const;
120 bool IsInCombatWith(Unit const* who) const;
121 void InheritCombatStatesFrom(Unit const* who);
122 void EndCombatBeyondRange(float range, bool includingPvP = false);
123
124 using UnitFilter = bool(Unit const* otherUnit);
125
126 // flags any pvp refs for suppression on owner's side - these refs will not generate combat until refreshed
127 void SuppressPvPCombat(UnitFilter* unitFilter = nullptr);
128 void EndAllPvECombat(UnitFilter* unitFilter = nullptr);
129 void RevalidateCombat();
130 void EndAllPvPCombat(UnitFilter* unitFilter = nullptr);
131 void EndAllCombat(UnitFilter* unitFilter = nullptr) { EndAllPvECombat(unitFilter); EndAllPvPCombat(unitFilter); }
132
133 CombatManager(CombatManager const&) = delete;
135
136 private:
137 static void NotifyAICombat(Unit* me, Unit* other);
138 void PutReference(ObjectGuid const& guid, CombatReference* ref);
139 void PurgeReference(ObjectGuid const& guid, bool pvp);
140 bool UpdateOwnerCombatState() const;
141 Unit* const _owner;
142 std::unordered_map<ObjectGuid, CombatReference*> _pveRefs;
143 std::unordered_map<ObjectGuid, PvPCombatReference*> _pvpRefs;
144
145 friend struct CombatReference;
146 friend struct PvPCombatReference;
147};
148
149#endif
@ IN_MILLISECONDS
Definition: Common.h:35
#define TC_GAME_API
Definition: Define.h:123
uint32_t uint32
Definition: Define.h:142
std::unordered_map< ObjectGuid, PvPCombatReference * > _pvpRefs
bool HasCombat() const
Unit *const _owner
CombatManager & operator=(CombatManager const &)=delete
std::unordered_map< ObjectGuid, PvPCombatReference * > const & GetPvPCombatRefs() const
std::unordered_map< ObjectGuid, CombatReference * > _pveRefs
CombatManager(Unit *owner)
std::unordered_map< ObjectGuid, CombatReference * > const & GetPvECombatRefs() const
CombatManager(CombatManager const &)=delete
void EndAllCombat(UnitFilter *unitFilter=nullptr)
Unit * GetOwner() const
bool(Unit const *otherUnit) UnitFilter
Definition: Unit.h:627
void Update(VignetteData &vignette, WorldObject const *owner)
Definition: Vignette.cpp:90
bool const _isPvP
Definition: CombatManager.h:56
Unit *const second
Definition: CombatManager.h:55
Unit *const first
Definition: CombatManager.h:54
CombatReference & operator=(CombatReference const &)=delete
bool IsSuppressedFor(Unit const *who) const
Definition: CombatManager.h:64
Unit * GetOther(Unit const *me) const
Definition: CombatManager.h:57
CombatReference(CombatReference const &)=delete
CombatReference(Unit *a, Unit *b, bool pvp=false)
Definition: CombatManager.h:70
void Suppress(Unit *who)
Definition: CombatManager.h:73
PvPCombatReference(Unit *first, Unit *second)
Definition: CombatManager.h:87