Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
BattlePetSpawnMgr.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 "BattlePetSpawnMgr.h"
7#include "Creature.h"
8#include "DatabaseEnv.h"
9#include "DBCStores.h"
10#include "DB2Stores.h"
11#include "Log.h"
12#include "Map.h"
13#include "ObjectAccessor.h"
14#include "ObjectMgr.h"
15#include "SharedDefines.h"
16#include "Util.h"
17#include "World.h"
18
19#include <unordered_map>
20
21namespace
22{
23 uint32 const BattlePetSpawnMgrUpdateInterval = 2 * IN_MILLISECONDS;
24
25 int32 BattlePetWildPoolMapForZone(uint32 zoneId)
26 {
27 typedef std::unordered_map<uint32, int32> BattlePetWildPoolZoneMapCache;
28 static BattlePetWildPoolZoneMapCache zoneMapCache;
29
30 BattlePetWildPoolZoneMapCache::const_iterator cacheItr = zoneMapCache.find(zoneId);
31 if (cacheItr != zoneMapCache.end())
32 return cacheItr->second;
33
34 for (uint32 i = 0; i < sAreaStore.GetNumRows(); ++i)
35 {
36 AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(i);
37 if (areaEntry && areaEntry->m_ID == zoneId)
38 {
39 zoneMapCache[zoneId] = int32(areaEntry->m_ContinentID);
40 return int32(areaEntry->m_ContinentID);
41 }
42 }
43
44 zoneMapCache[zoneId] = -1;
45 return -1;
46 }
47
48 uint8 BattlePetWildPoolLevel(Creature const& source, uint8 minLevel, uint8 maxLevel)
49 {
50 if (!minLevel)
51 minLevel = 1;
52
53 if (!maxLevel || maxLevel < minLevel)
54 maxLevel = minLevel;
55
56 if (maxLevel == minLevel)
57 return minLevel;
58
59 return uint8(minLevel + (rand32() % (uint32(maxLevel) - minLevel + 1)));
60 }
61
62 uint8 BattlePetWildPoolMaxCount(uint8 databaseMax)
63 {
64 if (!databaseMax)
65 return 0;
66
68 if (!configuredMin || databaseMax >= configuredMin)
69 return databaseMax;
70
71 return uint8(configuredMin > 255 ? 255 : configuredMin);
72 }
73
74 uint32 BattlePetWildPoolZoneForCreature(Creature const* creature)
75 {
76 if (!creature || !creature->GetMap())
77 return 0;
78
79 return creature->GetMap()->GetZoneId(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ());
80 }
81}
82
88
90{
91 _mapPools.clear();
92 _updateTimer = 0;
93
94 uint32 oldMSTime = getMSTime();
95
96 QueryResult result = WorldDatabase.Query("SELECT zone, species, entry, max, minLevel, maxLevel FROM battle_pet_wild_pool");
97 if (!result)
98 {
99 SF_LOG_INFO("server.loading", ">> Loaded 0 battle pet wild pool definitions. DB table `battle_pet_wild_pool` is empty.");
100 return;
101 }
102
103 uint32 count = 0;
104 do
105 {
106 Field* fields = result->Fetch();
107 uint32 const zoneId = fields[0].GetUInt32();
108 uint16 const species = fields[1].GetUInt16();
109 uint32 const entry = fields[2].GetUInt32();
110 uint8 const max = fields[3].GetUInt8();
111 uint8 const minLevel = fields[4].GetUInt8();
112 uint8 const maxLevel = fields[5].GetUInt8();
113
114 BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(species);
115 if (!speciesEntry)
116 {
117 SF_LOG_ERROR("sql.sql", "Table `battle_pet_wild_pool` has invalid species %u for creature entry %u, skipped.", species, entry);
118 continue;
119 }
120
121 if (!sObjectMgr->GetCreatureTemplate(entry))
122 {
123 SF_LOG_ERROR("sql.sql", "Table `battle_pet_wild_pool` has invalid replacement source entry %u for species %u, skipped.", entry, species);
124 continue;
125 }
126
127 if (!sObjectMgr->GetCreatureTemplate(speciesEntry->NpcId))
128 {
129 SF_LOG_ERROR("sql.sql", "Table `battle_pet_wild_pool` species %u references missing creature template %u, skipped.", species, speciesEntry->NpcId);
130 continue;
131 }
132
133 int32 const mapId = BattlePetWildPoolMapForZone(zoneId);
134 if (mapId < 0)
135 {
136 SF_LOG_ERROR("sql.sql", "Table `battle_pet_wild_pool` has invalid zone %u for species %u, skipped.", zoneId, species);
137 continue;
138 }
139
140 BattlePetWildPoolTemplate spawnTemplate;
141 spawnTemplate.Species = species;
142 spawnTemplate.Entry = entry;
143 spawnTemplate.Max = BattlePetWildPoolMaxCount(max);
144 spawnTemplate.MinLevel = minLevel ? minLevel : 1;
145 spawnTemplate.MaxLevel = maxLevel >= spawnTemplate.MinLevel ? maxLevel : spawnTemplate.MinLevel;
146
147 _mapPools[uint32(mapId)][zoneId].AddTemplate(spawnTemplate);
148 ++count;
149 } while (result->NextRow());
150
151 SF_LOG_INFO("server.loading", ">> Loaded %u battle pet wild pool definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
152}
153
155{
156 _updateTimer += diff;
157 if (_updateTimer < BattlePetSpawnMgrUpdateInterval)
158 return;
159
160 _updateTimer = 0;
161 for (BattlePetMapPoolMap::iterator mapItr = _mapPools.begin(); mapItr != _mapPools.end(); ++mapItr)
162 for (BattlePetZonePoolMap::iterator zoneItr = mapItr->second.begin(); zoneItr != mapItr->second.end(); ++zoneItr)
163 zoneItr->second.Populate();
164}
165
167{
168 if (!creature || creature->m_isTempWorldObject)
169 return;
170
171 if (BattlePetWildZonePool* zonePool = GetZonePool(creature))
172 zonePool->OnCreatureAdded(creature);
173}
174
176{
177 if (!creature || creature->m_isTempWorldObject)
178 return;
179
180 if (BattlePetWildZonePool* zonePool = GetZonePool(creature))
181 zonePool->OnCreatureRemoved(creature);
182}
183
185{
186 if (!creature)
187 return false;
188
189 if (BattlePetWildZonePool* zonePool = GetZonePool(creature))
190 return zonePool->RemoveReplacement(creature);
191
192 return false;
193}
194
196{
197 if (!creature)
198 return false;
199
200 if (BattlePetWildZonePool const* zonePool = GetZonePool(creature))
201 return zonePool->IsReplacement(creature->GetGUID());
202
203 return false;
204}
205
207{
208 if (!creature)
209 return NULL;
210
211 BattlePetMapPoolMap::iterator mapItr = _mapPools.find(creature->GetMapId());
212 if (mapItr == _mapPools.end())
213 return NULL;
214
215 uint32 const zoneId = BattlePetWildPoolZoneForCreature(creature);
216 if (!zoneId)
217 return NULL;
218
219 BattlePetZonePoolMap::iterator zoneItr = mapItr->second.find(zoneId);
220 if (zoneItr == mapItr->second.end())
221 return NULL;
222
223 return &zoneItr->second;
224}
225
227{
228 if (!creature)
229 return NULL;
230
231 BattlePetMapPoolMap::const_iterator mapItr = _mapPools.find(creature->GetMapId());
232 if (mapItr == _mapPools.end())
233 return NULL;
234
235 uint32 const zoneId = BattlePetWildPoolZoneForCreature(creature);
236 if (!zoneId)
237 return NULL;
238
239 BattlePetZonePoolMap::const_iterator zoneItr = mapItr->second.find(zoneId);
240 if (zoneItr == mapItr->second.end())
241 return NULL;
242
243 return &zoneItr->second;
244}
245
247{
248 for (std::vector<BattlePetWildPoolTemplate>::const_iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
249 if (itr->Entry == spawnTemplate.Entry && itr->Species == spawnTemplate.Species)
250 return;
251
252 _templates.push_back(spawnTemplate);
253}
254
256{
257 for (std::vector<BattlePetWildPoolTemplate>::iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
258 {
259 BattlePetWildPoolTemplate& spawnTemplate = *itr;
260 if (!spawnTemplate.Max || spawnTemplate.Replacements.size() >= spawnTemplate.Max)
261 continue;
262
263 std::set<uint64> ready = spawnTemplate.ReadyForReplacement;
264 for (std::set<uint64>::const_iterator guidItr = ready.begin(); guidItr != ready.end(); ++guidItr)
265 {
266 if (spawnTemplate.Replacements.size() >= spawnTemplate.Max)
267 break;
268
269 SpawnReplacement(*guidItr, spawnTemplate);
270 }
271 }
272}
273
275{
276 if (!creature)
277 return;
278
279 for (std::vector<BattlePetWildPoolTemplate>::iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
280 {
281 BattlePetWildPoolTemplate& spawnTemplate = *itr;
282 if (spawnTemplate.Entry == creature->GetEntry())
283 spawnTemplate.ReadyForReplacement.insert(creature->GetGUID());
284 }
285}
286
288{
289 if (!creature)
290 return;
291
292 for (std::vector<BattlePetWildPoolTemplate>::iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
293 {
294 BattlePetWildPoolTemplate& spawnTemplate = *itr;
295 spawnTemplate.ReadyForReplacement.erase(creature->GetGUID());
296 RemoveReplacement(creature->GetGUID(), spawnTemplate);
297 }
298}
299
301{
302 if (!replacement)
303 return false;
304
305 uint64 const replacementGuid = replacement->GetGUID();
306 for (std::vector<BattlePetWildPoolTemplate>::iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
307 {
308 BattlePetWildPoolTemplate& spawnTemplate = *itr;
309 for (std::map<uint64, uint64>::const_iterator relationItr = spawnTemplate.Replacements.begin();
310 relationItr != spawnTemplate.Replacements.end(); ++relationItr)
311 {
312 if (relationItr->second != replacementGuid)
313 continue;
314
315 return RemoveReplacement(relationItr->first, spawnTemplate);
316 }
317 }
318
319 return false;
320}
321
323{
324 for (std::vector<BattlePetWildPoolTemplate>::const_iterator itr = _templates.begin(); itr != _templates.end(); ++itr)
325 for (std::map<uint64, uint64>::const_iterator relationItr = itr->Replacements.begin();
326 relationItr != itr->Replacements.end(); ++relationItr)
327 if (relationItr->second == guid)
328 return true;
329
330 return false;
331}
332
334{
335 if (spawnTemplate.Replacements.find(originalGuid) != spawnTemplate.Replacements.end())
336 {
337 spawnTemplate.ReadyForReplacement.erase(originalGuid);
338 return;
339 }
340
341 Creature* original = ObjectAccessor::GetObjectInWorld(originalGuid, static_cast<Creature*>(nullptr));
342 if (!original || !original->IsInWorld() || original->m_isTempWorldObject || original->GetEntry() != spawnTemplate.Entry)
343 {
344 spawnTemplate.ReadyForReplacement.erase(originalGuid);
345 return;
346 }
347
348 BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(spawnTemplate.Species);
349 if (!speciesEntry)
350 {
351 spawnTemplate.ReadyForReplacement.erase(originalGuid);
352 return;
353 }
354
355 Creature* replacement = new Creature();
356 replacement->m_isTempWorldObject = true;
357
358 if (!replacement->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), original->GetMap(),
359 speciesEntry->NpcId, 0, 0, original->GetPositionX(), original->GetPositionY(),
360 original->GetPositionZ(), original->GetOrientation()))
361 {
362 delete replacement;
363 spawnTemplate.ReadyForReplacement.erase(originalGuid);
364 return;
365 }
366
367 uint8 const level = BattlePetWildPoolLevel(*original, spawnTemplate.MinLevel, spawnTemplate.MaxLevel);
368 replacement->SetLevel(level);
372
373 if (!original->GetMap()->AddToMap(replacement))
374 {
375 delete replacement;
376 spawnTemplate.ReadyForReplacement.erase(originalGuid);
377 return;
378 }
379
380 original->DespawnOrUnsummon();
381 original->SetRespawnTime(MONTH);
382 original->RemoveCorpse(false);
383
384 spawnTemplate.Replacements[originalGuid] = replacement->GetGUID();
385 spawnTemplate.ReadyForReplacement.erase(originalGuid);
386}
387
389{
390 std::map<uint64, uint64>::iterator relationItr = spawnTemplate.Replacements.find(originalGuid);
391 if (relationItr == spawnTemplate.Replacements.end())
392 return false;
393
394 uint64 const replacementGuid = relationItr->second;
395 Creature* replacement = ObjectAccessor::GetObjectInWorld(replacementGuid, static_cast<Creature*>(nullptr));
396 if (replacement)
397 {
398 replacement->RemoveFromWorld();
399 replacement->AddObjectToRemoveList();
400 }
401
402 if (Creature* original = ObjectAccessor::GetObjectInWorld(originalGuid, static_cast<Creature*>(nullptr)))
403 {
404 if (CreatureData const* creatureData = original->GetCreatureData())
405 original->SetRespawnTime(creatureData->spawntimesecs);
406 else
407 original->SetRespawnTime(0);
408 }
409
410 spawnTemplate.Replacements.erase(relationItr);
411 spawnTemplate.ReadyForReplacement.erase(originalGuid);
412 return true;
413}
@ IN_MILLISECONDS
Definition Common.h:125
@ MONTH
Definition Common.h:123
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore(BattlePetSpeciesfmt)
DBCStorage< AreaTableEntry > sAreaStore(AreaTableEntryfmt)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
@ HIGHGUID_UNIT
#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
@ UNIT_NPC_FLAG_WILDPET_CAPTURABLE
Definition Unit.h:716
@ UNIT_FLAG_IMMUNE_TO_NPC
Definition Unit.h:634
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ UNIT_FIELD_WILD_BATTLE_PET_LEVEL
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_FLAGS
int32 rand32()
Definition Util.cpp:45
BattlePetMapPoolMap _mapPools
bool ResolveWildBattle(Creature *creature)
BattlePetWildZonePool * GetZonePool(Creature const *creature)
void OnCreatureAdded(Creature *creature)
void Update(uint32 diff)
bool IsWildBattlePetReplacement(Creature const *creature) const
void OnCreatureRemoved(Creature *creature)
static BattlePetSpawnMgr * instance()
void OnCreatureAdded(Creature *creature)
void SpawnReplacement(uint64 originalGuid, BattlePetWildPoolTemplate &spawnTemplate)
bool RemoveReplacement(Creature *replacement)
std::vector< BattlePetWildPoolTemplate > _templates
void AddTemplate(BattlePetWildPoolTemplate const &spawnTemplate)
void OnCreatureRemoved(Creature *creature)
bool IsReplacement(uint64 guid) const
void SetRespawnTime(uint32 respawn)
Definition Creature.h:598
void DespawnOrUnsummon(uint32 msTimeToDespawn=0)
void RemoveCorpse(bool setSpawnTime=true)
Definition Creature.cpp:230
bool m_isTempWorldObject
Definition Creature.h:664
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData *data=NULL)
Definition Creature.cpp:740
void RemoveFromWorld() OVERRIDE
Definition Creature.cpp:193
Definition Field.h:16
uint8 GetUInt8() const
Definition Field.h:26
uint16 GetUInt16() const
Definition Field.h:69
uint32 GetUInt32() const
Definition Field.h:105
uint32 GetZoneId(float x, float y, float z) const
Definition Map.h:335
bool AddToMap(T *)
Definition Map.cpp:504
static T * GetObjectInWorld(uint64 guid, T *)
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
uint32 GetEntry() const
Definition Object.h:125
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void SetLevel(uint8 lvl)
Definition Unit.cpp:5150
uint32 GetMapId() const
Definition Object.h:546
Map * GetMap() const
Definition Object.h:740
void AddObjectToRemoveList()
Definition Object.cpp:2550
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition Main.cpp:40
#define sWorld
Definition World.h:910
@ CONFIG_BATTLE_PET_WILD_SPAWN_MIN_COUNT
Definition World.h:363
uint32 m_ID
uint32 m_ContinentID
uint32 NpcId
std::set< uint64 > ReadyForReplacement
std::map< uint64, uint64 > Replacements
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