Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
CreatureGroups.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 "Creature.h"
7#include "CreatureGroups.h"
8#include "ObjectMgr.h"
9
10#include "CreatureAI.h"
11
12#define MAX_DESYNC 5.0f
13
15{
16 for (CreatureGroupInfoType::iterator itr = CreatureGroupMap.begin(); itr != CreatureGroupMap.end(); ++itr)
17 delete itr->second;
18}
19
21{
22 Map* map = member->FindMap();
23 if (!map)
24 return;
25
26 CreatureGroupHolderType::iterator itr = map->CreatureGroupHolder.find(groupId);
27
28 //Add member to an existing group
29 if (itr != map->CreatureGroupHolder.end())
30 {
31 SF_LOG_DEBUG("entities.unit", "Group found: %u, inserting creature GUID: %u, Group InstanceID %u", groupId, member->GetGUIDLow(), member->GetInstanceId());
32 itr->second->AddMember(member);
33 }
34 //Create new group
35 else
36 {
37 SF_LOG_DEBUG("entities.unit", "Group not found: %u. Creating new group.", groupId);
38 CreatureGroup* group = new CreatureGroup(groupId);
39 map->CreatureGroupHolder[groupId] = group;
40 group->AddMember(member);
41 }
42}
43
45{
46 SF_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: %u from group %u", group->GetId(), member->GetDBTableGUIDLow());
47 group->RemoveMember(member);
48
49 if (group->isEmpty())
50 {
51 Map* map = member->FindMap();
52 if (!map)
53 return;
54
55 SF_LOG_DEBUG("entities.unit", "Deleting group with InstanceID %u", member->GetInstanceId());
56 map->CreatureGroupHolder.erase(group->GetId());
57 delete group;
58 }
59}
60
62{
63 uint32 oldMSTime = getMSTime();
64
65 for (CreatureGroupInfoType::iterator itr = CreatureGroupMap.begin(); itr != CreatureGroupMap.end(); ++itr) // for reload case
66 delete itr->second;
67 CreatureGroupMap.clear();
68
69 //Get group data
70 QueryResult result = WorldDatabase.Query("SELECT leaderGUID, memberGUID, dist, angle, groupAI, point_1, point_2 FROM creature_formations ORDER BY leaderGUID");
71
72 if (!result)
73 {
74 SF_LOG_ERROR("server.loading", ">> Loaded 0 creatures in formations. DB table `creature_formations` is empty!");
75 return;
76 }
77
78 uint32 count = 0;
79 Field* fields;
80 FormationInfo* group_member;
81
82 do
83 {
84 fields = result->Fetch();
85
86 //Load group member data
87 group_member = new FormationInfo();
88 group_member->leaderGUID = fields[0].GetUInt32();
89 uint32 memberGUID = fields[1].GetUInt32();
90 group_member->groupAI = fields[4].GetUInt32();
91 group_member->point_1 = fields[5].GetUInt16();
92 group_member->point_2 = fields[6].GetUInt16();
93 //If creature is group leader we may skip loading of dist/angle
94 if (group_member->leaderGUID != memberGUID)
95 {
96 group_member->follow_dist = fields[2].GetFloat();
97 group_member->follow_angle = fields[3].GetFloat() * M_PI / 180;
98 }
99 else
100 {
101 group_member->follow_dist = 0;
102 group_member->follow_angle = 0;
103 }
104
105 // check data correctness
106 {
107 if (!sObjectMgr->GetCreatureData(group_member->leaderGUID))
108 {
109 SF_LOG_ERROR("sql.sql", "creature_formations table leader guid %u incorrect (not exist)", group_member->leaderGUID);
110 delete group_member;
111 continue;
112 }
113
114 if (!sObjectMgr->GetCreatureData(memberGUID))
115 {
116 SF_LOG_ERROR("sql.sql", "creature_formations table member guid %u incorrect (not exist)", memberGUID);
117 delete group_member;
118 continue;
119 }
120 }
121
122 CreatureGroupMap[memberGUID] = group_member;
123 ++count;
124 } while (result->NextRow());
125
126 SF_LOG_INFO("server.loading", ">> Loaded %u creatures in formations in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
127}
128
130{
131 SF_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding unit GUID: %u.", member->GetGUIDLow());
132
133 //Check if it is a leader
134 if (member->GetDBTableGUIDLow() == m_groupID)
135 {
136 SF_LOG_DEBUG("entities.unit", "Unit GUID: %u is formation leader. Adding group.", member->GetGUIDLow());
137 m_leader = member;
138 }
139
140 m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetDBTableGUIDLow())->second;
141 member->SetFormation(this);
142}
143
145{
146 if (m_leader == member)
147 m_leader = NULL;
148
149 m_members.erase(member);
150 member->SetFormation(NULL);
151}
152
154{
155 uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetDBTableGUIDLow()]->groupAI;
156 if (!groupAI)
157 return;
158
159 if (groupAI == 1 && member != m_leader)
160 return;
161
162 for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
163 {
164 if (m_leader) // avoid crash if leader was killed and reset.
165 SF_LOG_DEBUG("entities.unit", "GROUP ATTACK: group instance id %u calls member instid %u", m_leader->GetInstanceId(), member->GetInstanceId());
166
167 Creature* other = itr->first;
168
169 // Skip self
170 if (other == member)
171 continue;
172
173 if (!other->IsAlive())
174 continue;
175
176 if (other->GetVictim())
177 continue;
178
179 if (other->IsValidAttackTarget(target))
180 other->AI()->AttackStart(target);
181 }
182}
183
185{
186 for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
187 {
188 if (itr->first != m_leader && itr->first->IsAlive())
189 {
190 if (dismiss)
191 itr->first->GetMotionMaster()->Initialize();
192 else
193 itr->first->GetMotionMaster()->MoveIdle();
194 SF_LOG_DEBUG("entities.unit", "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", itr->first->GetGUIDLow());
195 }
196 }
197 m_Formed = !dismiss;
198}
199
200void CreatureGroup::LeaderMoveTo(float x, float y, float z)
201{
204 if (!m_leader)
205 return;
206
207 float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
208
209 for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
210 {
211 Creature* member = itr->first;
212 if (member == m_leader || !member->IsAlive() || member->GetVictim())
213 continue;
214
215 if (itr->second->point_1)
216 {
217 if (m_leader->GetCurrentWaypointID() == itr->second->point_1)
218 itr->second->follow_angle = (2 * M_PI) - itr->second->follow_angle;
219 if (m_leader->GetCurrentWaypointID() == itr->second->point_2)
220 itr->second->follow_angle = (2 * M_PI) + itr->second->follow_angle;
221 }
222
223 float angle = itr->second->follow_angle;
224 float dist = itr->second->follow_dist;
225
226 float dx = x + std::cos(angle + pathangle) * dist;
227 float dy = y + std::sin(angle + pathangle) * dist;
228 float dz = z;
229
232
233 member->UpdateGroundPositionZ(dx, dy, dz);
234
235 if (member->IsWithinDist(m_leader, dist + MAX_DESYNC))
236 member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
237 else
238 member->SetWalk(false);
239
240 member->GetMotionMaster()->MovePoint(0, dx, dy, dz);
241 member->SetHomePosition(dx, dy, dz, pathangle);
242 }
243}
#define M_PI
Definition Common.h:192
#define MAX_DESYNC
#define sFormationMgr
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
#define sObjectMgr
Definition ObjectMgr.h:1617
Skyfire::AutoPtr< ResultSet, Skyfire::Mutex > QueryResult
Definition QueryResult.h:48
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:22
uint32 getMSTime()
Definition Timer.h:12
uint32 GetId() const
void FormationReset(bool dismiss)
bool isEmpty() const
CreatureGroupMemberType m_members
void RemoveMember(Creature *member)
void MemberAttackStart(Creature *member, Unit *target)
void LeaderMoveTo(float x, float y, float z)
Creature * m_leader
void AddMember(Creature *member)
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:626
uint32 GetDBTableGUIDLow() const
Definition Creature.h:445
void SetFormation(CreatureGroup *formation)
Definition Creature.h:644
CreatureAI * AI() const
Definition Creature.h:483
Definition Field.h:16
uint16 GetUInt16() const
Definition Field.h:69
float GetFloat() const
Definition Field.h:177
uint32 GetUInt32() const
Definition Field.h:105
void RemoveCreatureFromGroup(CreatureGroup *group, Creature *creature)
CreatureGroupInfoType CreatureGroupMap
void AddCreatureToGroup(uint32 group_id, Creature *creature)
void LoadCreatureFormations()
Definition Map.h:238
CreatureGroupHolderType CreatureGroupHolder
Definition Map.h:426
void MovePoint(uint32 id, Position const &pos, bool generatePath=true)
uint32 GetGUIDLow() const
Definition Object.h:120
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
bool IsValidAttackTarget(Unit const *target) const
Definition Unit.cpp:3810
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
void SetUnitMovementFlags(uint32 f)
Definition Unit.h:2636
bool IsAlive() const
Definition Unit.h:2032
bool SetWalk(bool enable)
Definition Unit.cpp:9137
Unit * GetVictim() const
Definition Unit.h:1468
Map * FindMap() const
Definition Object.h:741
uint32 GetInstanceId() const
Definition Object.h:638
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:1978
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition Object.cpp:1730
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition Main.cpp:40
void NormalizeMapCoord(float &c)