Merge pull request #9280 from horn/summons
Core/Summons: Implement summon groups system to be able to summon multiple NPCs at once without need of hardcoding the positions. Almost all hardcoded positions can now be moved to DB.
This commit is contained in:
commit
e3e09b93e2
8 files changed
+202
No files matched your search
@@ -0,0 +1,16 @@
|
||||
DROP TABLE IF EXISTS `creature_summon_groups`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `creature_summon_groups` (
|
||||
`summonerId` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`summonerType` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`groupId` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`entry` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`position_x` float NOT NULL DEFAULT '0',
|
||||
`position_y` float NOT NULL DEFAULT '0',
|
||||
`position_z` float NOT NULL DEFAULT '0',
|
||||
`orientation` float NOT NULL DEFAULT '0',
|
||||
`summonType` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`summonTime` int(10) unsigned NOT NULL DEFAULT '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -21,6 +21,22 @@
|
||||
|
||||
#include "Creature.h"
|
||||
|
||||
enum SummonerType
|
||||
{
|
||||
SUMMONER_TYPE_CREATURE = 0,
|
||||
SUMMONER_TYPE_GAMEOBJECT = 1,
|
||||
SUMMONER_TYPE_MAP = 2
|
||||
};
|
||||
|
||||
/// Stores data for temp summons
|
||||
struct TempSummonData
|
||||
{
|
||||
uint32 entry; ///< Entry of summoned creature
|
||||
Position pos; ///< Position, where should be creature spawned
|
||||
TempSummonType type; ///< Summon type, see TempSummonType for available types
|
||||
uint32 time; ///< Despawn time, usable only with certain temp summon types
|
||||
};
|
||||
|
||||
class TempSummon : public Creature
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -2315,6 +2315,24 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
|
||||
return summon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons group of creatures.
|
||||
*
|
||||
* @param group Id of group to summon.
|
||||
* @param list List to store pointers to summoned creatures.
|
||||
*/
|
||||
|
||||
void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
|
||||
{
|
||||
std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetId(), SUMMONER_TYPE_MAP, group);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
|
||||
if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, NULL, itr->time))
|
||||
list.push_back(summon);
|
||||
}
|
||||
|
||||
void WorldObject::SetZoneScript()
|
||||
{
|
||||
if (Map* map = FindMap())
|
||||
@@ -2394,6 +2412,25 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
|
||||
return summon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons group of creatures. Should be called only by instances of Creature and GameObject classes.
|
||||
*
|
||||
* @param group Id of group to summon.
|
||||
* @param list List to store pointers to summoned creatures.
|
||||
*/
|
||||
void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
|
||||
{
|
||||
ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
|
||||
|
||||
std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
|
||||
if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, itr->time))
|
||||
list.push_back(summon);
|
||||
}
|
||||
|
||||
Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const
|
||||
{
|
||||
Creature* creature = NULL;
|
||||
|
||||
@@ -793,6 +793,7 @@ class WorldObject : public Object, public WorldLocation
|
||||
}
|
||||
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
|
||||
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
|
||||
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list);
|
||||
|
||||
Creature* FindNearestCreature(uint32 entry, float range, bool alive = true) const;
|
||||
GameObject* FindNearestGameObject(uint32 entry, float range) const;
|
||||
|
||||
@@ -1421,6 +1421,92 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadTempSummons()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
QueryResult result = WorldDatabase.Query("SELECT summonerId, summonerType, groupId, entry, position_x, position_y, position_z, orientation, summonType, summonTime FROM creature_summon_groups");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 temp summons. DB table `creature_summon_groups` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 summonerId = fields[0].GetUInt32();
|
||||
SummonerType summonerType = SummonerType(fields[1].GetUInt8());
|
||||
uint8 group = fields[2].GetUInt8();
|
||||
|
||||
switch (summonerType)
|
||||
{
|
||||
case SUMMONER_TYPE_CREATURE:
|
||||
if (!GetCreatureTemplate(summonerId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for creature summoner type, skipped.", summonerId);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case SUMMONER_TYPE_GAMEOBJECT:
|
||||
if (!GetGameObjectTemplate(summonerId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for gameobject summoner type, skipped.", summonerId);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case SUMMONER_TYPE_MAP:
|
||||
if (!sMapStore.LookupEntry(summonerId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for map summoner type, skipped.", summonerId);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has unhandled summoner type %u for summoner %u, skipped.", summonerType, summonerId);
|
||||
continue;
|
||||
}
|
||||
|
||||
TempSummonData data;
|
||||
data.entry = fields[3].GetUInt32();
|
||||
|
||||
if (!GetCreatureTemplate(data.entry))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has creature in group [Summoner ID: %u, Summoner Type: %u, Group ID: %u] with non existing creature entry %u, skipped.", summonerId, summonerType, group, data.entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
float posX = fields[4].GetFloat();
|
||||
float posY = fields[5].GetFloat();
|
||||
float posZ = fields[6].GetFloat();
|
||||
float orientation = fields[7].GetFloat();
|
||||
|
||||
data.pos.Relocate(posX, posY, posZ, orientation);
|
||||
|
||||
data.type = TempSummonType(fields[8].GetUInt8());
|
||||
|
||||
if (data.type > TEMPSUMMON_MANUAL_DESPAWN)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has unhandled temp summon type %u in group [Summoner ID: %u, Summoner Type: %u, Group ID: %u] for creature entry %u, skipped.", data.type, summonerId, summonerType, group, data.entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
data.time = fields[9].GetUInt32();
|
||||
|
||||
TempSummonGroupKey key(summonerId, summonerType, group);
|
||||
_tempSummonDataStore[key].push_back(data);
|
||||
|
||||
++count;
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u temp summons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadCreatures()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Creature.h"
|
||||
#include "DynamicObject.h"
|
||||
#include "GameObject.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Corpse.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ItemPrototype.h"
|
||||
@@ -416,9 +417,29 @@ struct TrinityStringLocale
|
||||
StringVector Content;
|
||||
};
|
||||
|
||||
/// Key for storing temp summon data in TempSummonDataContainer
|
||||
struct TempSummonGroupKey
|
||||
{
|
||||
TempSummonGroupKey(uint32 summonerEntry, SummonerType summonerType, uint8 group)
|
||||
: _summonerEntry(summonerEntry), _summonerType(summonerType), _summonGroup(group)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(TempSummonGroupKey const& rhs) const
|
||||
{
|
||||
return memcmp(this, &rhs, sizeof(TempSummonGroupKey)) < 0;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _summonerEntry; ///< Summoner's entry
|
||||
SummonerType _summonerType; ///< Summoner's type, see SummonerType for available types
|
||||
uint8 _summonGroup; ///< Summon's group id
|
||||
};
|
||||
|
||||
typedef std::map<uint64, uint64> LinkedRespawnContainer;
|
||||
typedef UNORDERED_MAP<uint32, CreatureData> CreatureDataContainer;
|
||||
typedef UNORDERED_MAP<uint32, GameObjectData> GameObjectDataContainer;
|
||||
typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDataContainer;
|
||||
typedef UNORDERED_MAP<uint32, CreatureLocale> CreatureLocaleContainer;
|
||||
typedef UNORDERED_MAP<uint32, GameObjectLocale> GameObjectLocaleContainer;
|
||||
typedef UNORDERED_MAP<uint32, ItemLocale> ItemLocaleContainer;
|
||||
@@ -876,6 +897,7 @@ class ObjectMgr
|
||||
void LoadCreatureTemplates();
|
||||
void LoadCreatureTemplateAddons();
|
||||
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
|
||||
void LoadTempSummons();
|
||||
void LoadCreatures();
|
||||
void LoadLinkedRespawn();
|
||||
bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid);
|
||||
@@ -981,6 +1003,24 @@ class ObjectMgr
|
||||
return _mapObjectGuidsStore[MAKE_PAIR32(mapid, spawnMode)][cell_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets temp summon data for all creatures of specified group.
|
||||
*
|
||||
* @param summonerId Summoner's entry.
|
||||
* @param summonerType Summoner's type, see SummonerType for available types.
|
||||
* @param group Id of required group.
|
||||
*
|
||||
* @return null if group was not found, otherwise reference to the creature group data
|
||||
*/
|
||||
std::vector<TempSummonData> const* GetSummonGroup(uint32 summonerId, SummonerType summonerType, uint8 group) const
|
||||
{
|
||||
TempSummonDataContainer::const_iterator itr = _tempSummonDataStore.find(TempSummonGroupKey(summonerId, summonerType, group));
|
||||
if (itr != _tempSummonDataStore.end())
|
||||
return &itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CreatureData const* GetCreatureData(uint32 guid) const
|
||||
{
|
||||
CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid);
|
||||
@@ -1294,6 +1334,8 @@ class ObjectMgr
|
||||
GameObjectDataContainer _gameObjectDataStore;
|
||||
GameObjectLocaleContainer _gameObjectLocaleStore;
|
||||
GameObjectTemplateContainer _gameObjectTemplateStore;
|
||||
/// Stores temp summon data grouped by summoner's entry, summoner's type and group id
|
||||
TempSummonDataContainer _tempSummonDataStore;
|
||||
|
||||
ItemTemplateContainer _itemTemplateStore;
|
||||
ItemLocaleContainer _itemLocaleStore;
|
||||
|
||||
@@ -435,6 +435,7 @@ class Map : public GridRefManager<NGridType>
|
||||
void UpdateIteratorBack(Player* player);
|
||||
|
||||
TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0);
|
||||
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list);
|
||||
Creature* GetCreature(uint64 guid);
|
||||
GameObject* GetGameObject(uint64 guid);
|
||||
DynamicObject* GetDynamicObject(uint64 guid);
|
||||
|
||||
@@ -1432,6 +1432,9 @@ void World::SetInitialWorldSettings()
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature Data...");
|
||||
sObjectMgr->LoadCreatures();
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Temporary Summon Data...");
|
||||
sObjectMgr->LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading pet levelup spells...");
|
||||
sSpellMgr->LoadPetLevelupSpellMap();
|
||||
|
||||
|
||||
Reference in new issue
Block a user