[11994] Implement creature_linking by guid

This commit is contained in:
Schmoozerd 2012-05-10 22:22:16 +02:00
parent 74e3e55668
commit d41974b38b
6 changed files with 258 additions and 73 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_11985_01_mangos_gameobject_template_scripts` bit(1) default NULL `required_11994_01_mangos_creature_linking` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -966,6 +966,28 @@ LOCK TABLES `creature_involvedrelation` WRITE;
/*!40000 ALTER TABLE `creature_involvedrelation` ENABLE KEYS */; /*!40000 ALTER TABLE `creature_involvedrelation` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `creature_linking`
--
DROP TABLE IF EXISTS creature_linking;
CREATE TABLE `creature_linking` (
`guid` int(10) UNSIGNED NOT NULL COMMENT 'creature.guid of the slave mob that is linked',
`master_guid` int(10) UNSIGNED NOT NULL COMMENT 'master to trigger events',
`flag` mediumint(8) UNSIGNED NOT NULL COMMENT 'flag - describing what should happen when',
PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature Linking System';
--
-- Dumping data for table `creature_linking`
--
LOCK TABLES `creature_linking` WRITE;
/*!40000 ALTER TABLE `creature_linking` DISABLE KEYS */;
/*!40000 ALTER TABLE `creature_linking` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `creature_linking_template` -- Table structure for table `creature_linking_template`
-- --

View file

@ -0,0 +1,13 @@
ALTER TABLE db_version CHANGE COLUMN required_11985_01_mangos_gameobject_template_scripts required_11994_01_mangos_creature_linking bit;
--
-- Table structure for table `creature_linking`
--
DROP TABLE IF EXISTS creature_linking;
CREATE TABLE `creature_linking` (
`guid` int(10) UNSIGNED NOT NULL COMMENT 'creature.guid of the slave mob that is linked',
`master_guid` int(10) UNSIGNED NOT NULL COMMENT 'master to trigger events',
`flag` mediumint(8) UNSIGNED NOT NULL COMMENT 'flag - describing what should happen when',
PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature Linking System';

View file

@ -43,15 +43,20 @@
INSTANTIATE_SINGLETON_1(CreatureLinkingMgr); INSTANTIATE_SINGLETON_1(CreatureLinkingMgr);
#define INVALID_MAP_ID 0xFFFFFFFF
/* ********************************************************* /* *********************************************************
* Method to Load From DB * Method to Load From DB
* DB Format: entry, map, master_entry, flag * DB Format: entry, map, master_entry, flag, search_radius for `creature_linking_template` (by entry)
* 0 1 2 3 * 0 1 2 3 4
* DB Format: guid, master_guid, flag for `creature_linking` (by guid)
* 0 1 2
* ************************************** * **************************************
* entry: creature_template.entry * entry/guid: creature_template.entry/guid
* map: Map on which the NPC has to be * map: Map on which the NPC has to be
* master_entry creature_template.entry of the npc, that shall trigger the actions * master_entry/master_guid creature_template.entry of the npc, that shall trigger the actions
* flag: flag value, of type CreatureLinkingFlags * flag: flag value, of type CreatureLinkingFlags
* search_radius: radius, in which master and slave must be spawned so that they are linked together
* *
* ***************************************************** */ * ***************************************************** */
@ -59,7 +64,9 @@ void CreatureLinkingMgr::LoadFromDB()
{ {
// Clear maps // Clear maps
m_creatureLinkingMap.clear(); m_creatureLinkingMap.clear();
m_creatureLinkingGuidMap.clear();
m_eventTriggers.clear(); // master m_eventTriggers.clear(); // master
m_eventGuidTriggers.clear();
QueryResult* result = WorldDatabase.Query("SELECT entry, map, master_entry, flag, search_range FROM creature_linking_template"); QueryResult* result = WorldDatabase.Query("SELECT entry, map, master_entry, flag, search_range FROM creature_linking_template");
@ -77,7 +84,6 @@ void CreatureLinkingMgr::LoadFromDB()
} }
BarGoLink bar((int)result->GetRowCount()); BarGoLink bar((int)result->GetRowCount());
do do
{ {
bar.step(); bar.step();
@ -92,7 +98,7 @@ void CreatureLinkingMgr::LoadFromDB()
tmp.searchRange = fields[4].GetUInt16(); tmp.searchRange = fields[4].GetUInt16();
tmp.masterDBGuid = 0; // Will be initialized for unique mobs later (only for spawning dependend) tmp.masterDBGuid = 0; // Will be initialized for unique mobs later (only for spawning dependend)
if (!IsLinkingEntryValid(entry, &tmp)) if (!IsLinkingEntryValid(entry, &tmp, true))
continue; continue;
// Store db-guid for master of whom pTmp is spawn dependend (only non-local bosses) // Store db-guid for master of whom pTmp is spawn dependend (only non-local bosses)
@ -117,55 +123,136 @@ void CreatureLinkingMgr::LoadFromDB()
while (result->NextRow()); while (result->NextRow());
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded creature linking for %u creature-IDs", count); sLog.outString(">> Loaded creature linking for %u creature-entries", count);
delete result;
result = WorldDatabase.Query("SELECT guid, master_guid, flag FROM creature_linking");
count = 0;
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString(">> Table creature_linking is empty.");
sLog.outString();
return;
}
BarGoLink guidBar((int)result->GetRowCount());
do
{
guidBar.step();
Field* fields = result->Fetch();
CreatureLinkingInfo tmp;
uint32 guid = fields[0].GetUInt32();
tmp.mapId = INVALID_MAP_ID; // some invalid value, this marks the guid-linking
tmp.masterId = fields[1].GetUInt32();
tmp.linkingFlag = fields[2].GetUInt16();
tmp.masterDBGuid = tmp.masterId;
tmp.searchRange = 0;
if (!IsLinkingEntryValid(guid, &tmp, false))
continue;
++count;
// Add it to the map
m_creatureLinkingGuidMap.insert(CreatureLinkingMap::value_type(guid, tmp));
// Store master_guid
m_eventGuidTriggers.insert(tmp.masterId);
}
while (result->NextRow());
sLog.outString();
sLog.outString(">> Loaded creature linking for %u creature-Guids", count);
delete result; delete result;
} }
// This function is used to check if a DB-Entry is valid // This function is used to check if a DB-Entry is valid
bool CreatureLinkingMgr::IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingInfo* pTmp) bool CreatureLinkingMgr::IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingInfo* pTmp, bool byEntry)
{ {
// Basic checks first // Basic checks first
CreatureInfo const* pInfo = ObjectMgr::GetCreatureTemplate(slaveEntry); if (byEntry) // Entry given
if (!pInfo)
{ {
sLog.outErrorDb("`creature_linking_template` has a non existing slave_entry (ID: %u), skipped.", slaveEntry); CreatureInfo const* pInfo = ObjectMgr::GetCreatureTemplate(slaveEntry);
return false; CreatureInfo const* pMasterInfo = ObjectMgr::GetCreatureTemplate(pTmp->masterId);
}
pInfo = ObjectMgr::GetCreatureTemplate(pTmp->masterId); if (!pInfo)
if (!pInfo) {
sLog.outErrorDb("`creature_linking_template` has a non existing slave_entry (slave: %u, master %u), skipped.", slaveEntry, pTmp->masterId);
return false;
}
if (!pMasterInfo)
{
sLog.outErrorDb("`creature_linking_template` has a non existing master_entry (slave: %u, master %u), skipped", slaveEntry, pTmp->masterId);
return false;
}
if (pTmp->mapId && !sMapStore.LookupEntry(pTmp->mapId))
{
sLog.outErrorDb("`creature_linking_template` has a non existing map %u (slave %u, master %u), skipped", pTmp->mapId, slaveEntry, pTmp->masterId);
return false;
}
}
else // guid given
{ {
sLog.outErrorDb("`creature_linking_template` has a non existing master_entry (ID: %u), skipped", pTmp->masterId); CreatureData const* slaveData = sObjectMgr.GetCreatureData(slaveEntry);
return false; CreatureData const* masterData = sObjectMgr.GetCreatureData(pTmp->masterId);
if (!slaveData)
{
sLog.outErrorDb("`creature_linking` has a non existing slave (guid: %u, master_guid %u), skipped", slaveEntry, pTmp->masterId);
return false;
}
if (!masterData)
{
sLog.outErrorDb("`creature_linking` has a non existing master (guid: %u,, master_guid: %u), skipped", slaveEntry, pTmp->masterId);
return false;
}
if (slaveData->mapid != masterData->mapid)
{
sLog.outErrorDb("`creature_linking` has a slave and master on different maps (guid: %u, master_guid: %u), skipped", slaveEntry, pTmp->masterId);
return false;
}
} }
if (pTmp->linkingFlag & ~(LINKING_FLAG_INVALID - 1) || pTmp->linkingFlag == 0) if (pTmp->linkingFlag & ~(LINKING_FLAG_INVALID - 1) || pTmp->linkingFlag == 0)
{ {
sLog.outErrorDb("`creature_linking_template` has invalid flag, (entry: %u, map: %u, flags: %u), skipped", slaveEntry, pTmp->mapId, pTmp->linkingFlag); sLog.outErrorDb("`creature_linking%s` has invalid flag, (entry: %u, map: %u, flags: %u), skipped", byEntry ? "_template" : "", slaveEntry, pTmp->mapId, pTmp->linkingFlag);
return false; return false;
} }
// Additional checks, depending on flags // Additional checks, depending on flags
if (pTmp->linkingFlag & FLAG_DESPAWN_ON_RESPAWN && slaveEntry == pTmp->masterId) if (pTmp->linkingFlag & FLAG_DESPAWN_ON_RESPAWN && slaveEntry == pTmp->masterId)
{ {
sLog.outErrorDb("`creature_linking_template` has pointless FLAG_DESPAWN_ON_RESPAWN for self, (entry: %u, map: %u), skipped", slaveEntry, pTmp->mapId); sLog.outErrorDb("`creature_linking%s` has pointless FLAG_DESPAWN_ON_RESPAWN for self, (entry: %u, map: %u), skipped", byEntry ? "_template" : "", slaveEntry, pTmp->mapId);
return false; return false;
} }
// Check for uniqueness of mob whom is followed, on whom spawning is dependend if (byEntry)
if (pTmp->searchRange == 0 && pTmp->linkingFlag & (FLAG_FOLLOW | FLAG_CANT_SPAWN_IF_BOSS_DEAD | FLAG_CANT_SPAWN_IF_BOSS_ALIVE))
{ {
// Painfully slow, needs better idea // Check for uniqueness of mob whom is followed, on whom spawning is dependend
QueryResult *result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id=%u AND map=%u", pTmp->masterId, pTmp->mapId); if (pTmp->searchRange == 0 && pTmp->linkingFlag & (FLAG_FOLLOW | FLAG_CANT_SPAWN_IF_BOSS_DEAD | FLAG_CANT_SPAWN_IF_BOSS_ALIVE))
if (result)
{ {
if ((*result)[0].GetUInt32() > 1) // Painfully slow, needs better idea
sLog.outErrorDb("`creature_linking_template` has FLAG_FOLLOW, but non unique master, (entry: %u, map: %u, master: %u)", slaveEntry, pTmp->mapId, pTmp->masterId); QueryResult *result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id=%u AND map=%u", pTmp->masterId, pTmp->mapId);
delete result; if (result)
{
if ((*result)[0].GetUInt32() > 1)
sLog.outErrorDb("`creature_linking_template` has FLAG_FOLLOW, but non unique master, (entry: %u, map: %u, master: %u)", slaveEntry, pTmp->mapId, pTmp->masterId);
delete result;
}
} }
} }
// All checks are passed, entry is valid // All checks are passed, entry/guid is valid
return true; return true;
} }
@ -182,11 +269,14 @@ enum EventMask
// This functions checks if the NPC has linked NPCs for dynamic action // This functions checks if the NPC has linked NPCs for dynamic action
bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature) bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature)
{ {
// TODO could actually be improved to also check for the map // Entry case
// Depends if we want to cache this bool into Creature or not
if (m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end()) if (m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end())
return true; return true;
// Guid case
if (m_eventGuidTriggers.find(pCreature->GetGUIDLow()) != m_eventGuidTriggers.end())
return true;
// Also return true for npcs that trigger reverse actions, or for followers(needed in respawn) // Also return true for npcs that trigger reverse actions, or for followers(needed in respawn)
if (CreatureLinkingInfo const* pInfo = GetLinkedTriggerInformation(pCreature)) if (CreatureLinkingInfo const* pInfo = GetLinkedTriggerInformation(pCreature))
return pInfo->linkingFlag & EVENT_MASK_TRIGGER_TO; return pInfo->linkingFlag & EVENT_MASK_TRIGGER_TO;
@ -195,6 +285,7 @@ bool CreatureLinkingMgr::IsLinkedEventTrigger(Creature* pCreature)
} }
// This function check if the NPC is a master to other NPCs // This function check if the NPC is a master to other NPCs
// return true only for masters stored by entry - this prevents adding them to master-holder maps
bool CreatureLinkingMgr::IsLinkedMaster(Creature* pCreature) bool CreatureLinkingMgr::IsLinkedMaster(Creature* pCreature)
{ {
return m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end(); return m_eventTriggers.find(pCreature->GetEntry()) != m_eventTriggers.end();
@ -212,7 +303,13 @@ bool CreatureLinkingMgr::IsSpawnedByLinkedMob(Creature* pCreature)
// Depends of the map // Depends of the map
CreatureLinkingInfo const* CreatureLinkingMgr::GetLinkedTriggerInformation(Creature* pCreature) CreatureLinkingInfo const* CreatureLinkingMgr::GetLinkedTriggerInformation(Creature* pCreature)
{ {
CreatureLinkingMapBounds bounds = m_creatureLinkingMap.equal_range(pCreature->GetEntry()); // guid case
CreatureLinkingMapBounds bounds = m_creatureLinkingGuidMap.equal_range(pCreature->GetGUIDLow());
for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
return &(iter->second);
// entry case
bounds = m_creatureLinkingMap.equal_range(pCreature->GetEntry());
for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter) for (CreatureLinkingMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{ {
if (iter->second.mapId == pCreature->GetMapId()) if (iter->second.mapId == pCreature->GetMapId())
@ -229,6 +326,31 @@ void CreatureLinkingHolder::AddSlaveToHolder(Creature* pCreature)
if (!pInfo) if (!pInfo)
return; return;
if (pInfo->mapId == INVALID_MAP_ID) // Guid case, store master->slaves for fast access
{
HolderMapBounds bounds = m_holderGuidMap.equal_range(pInfo->masterId);
for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
{
if (itr->second.linkingFlag == pInfo->linkingFlag)
{
itr->second.linkedGuids.push_back(pCreature->GetObjectGuid());
pCreature = NULL; // Store that is was handled
break;
}
}
// If this is a new flag, insert new entry
if (pCreature)
{
InfoAndGuids tmp;
tmp.linkedGuids.push_back(pCreature->GetObjectGuid());
tmp.linkingFlag = pInfo->linkingFlag;
tmp.searchRange = 0;
m_holderGuidMap.insert(HolderMap::value_type(pInfo->masterId, tmp));
}
return;
}
// First try to find holder with same flag // First try to find holder with same flag
HolderMapBounds bounds = m_holderMap.equal_range(pInfo->masterId); HolderMapBounds bounds = m_holderMap.equal_range(pInfo->masterId);
for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr) for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
@ -258,7 +380,7 @@ void CreatureLinkingHolder::AddMasterToHolder(Creature* pCreature)
if (pCreature->IsPet()) if (pCreature->IsPet())
return; return;
// Only add master NPCs // Only add master NPCs (by entry)
if (!sCreatureLinkingMgr.IsLinkedMaster(pCreature)) if (!sCreatureLinkingMgr.IsLinkedMaster(pCreature))
return; return;
@ -290,15 +412,19 @@ void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventTyp
switch (eventType) switch (eventType)
{ {
case LINKING_EVENT_AGGRO: eventFlagFilter = EVENT_MASK_ON_AGGRO; reverseEventFlagFilter = FLAG_TO_AGGRO_ON_AGGRO; break; case LINKING_EVENT_AGGRO: eventFlagFilter = EVENT_MASK_ON_AGGRO; reverseEventFlagFilter = FLAG_TO_AGGRO_ON_AGGRO; break;
case LINKING_EVENT_EVADE: eventFlagFilter = EVENT_MASK_ON_EVADE; reverseEventFlagFilter = FLAG_TO_RESPAWN_ON_EVADE; break; case LINKING_EVENT_EVADE: eventFlagFilter = EVENT_MASK_ON_EVADE; reverseEventFlagFilter = FLAG_TO_RESPAWN_ON_EVADE; break;
case LINKING_EVENT_DIE: eventFlagFilter = EVENT_MASK_ON_DIE; reverseEventFlagFilter = 0; break; case LINKING_EVENT_DIE: eventFlagFilter = EVENT_MASK_ON_DIE; reverseEventFlagFilter = 0; break;
case LINKING_EVENT_RESPAWN: eventFlagFilter = EVENT_MASK_ON_RESPAWN; reverseEventFlagFilter = FLAG_FOLLOW; break; case LINKING_EVENT_RESPAWN: eventFlagFilter = EVENT_MASK_ON_RESPAWN; reverseEventFlagFilter = FLAG_FOLLOW; break;
} }
// Process Slaves // Process Slaves (by entry)
HolderMapBounds bounds = m_holderMap.equal_range(pSource->GetEntry()); HolderMapBounds bounds = m_holderMap.equal_range(pSource->GetEntry());
// Get all holders for this boss for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy);
// Process Slaves (by guid)
bounds = m_holderGuidMap.equal_range(pSource->GetGUIDLow());
for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr) for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy); ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy);
@ -307,31 +433,44 @@ void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventTyp
{ {
if (pInfo->linkingFlag & reverseEventFlagFilter) if (pInfo->linkingFlag & reverseEventFlagFilter)
{ {
BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId); Creature* pMaster = NULL;
for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr) if (pInfo->mapId != INVALID_MAP_ID) // entry case
{ {
Creature* pMaster = pSource->GetMap()->GetCreature(itr->second); BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
if (pMaster && IsSlaveInRangeOfBoss(pSource, pMaster, pInfo->searchRange)) for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
{ {
switch (eventType) pMaster = pSource->GetMap()->GetCreature(itr->second);
{ if (pMaster && IsSlaveInRangeOfBoss(pSource, pMaster, pInfo->searchRange))
case LINKING_EVENT_AGGRO: break;
if (pMaster->IsControlledByPlayer()) }
return; }
else // guid case
{
CreatureData const* masterData = sObjectMgr.GetCreatureData(pInfo->masterDBGuid);
CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(masterData->id);
pMaster = pSource->GetMap()->GetCreature(ObjectGuid(cInfo->GetHighGuid(), cInfo->Entry, pInfo->masterDBGuid));
}
if (pMaster->isInCombat()) if (pMaster)
pMaster->SetInCombatWith(pEnemy); {
else switch (eventType)
pMaster->AI()->AttackStart(pEnemy); {
break; case LINKING_EVENT_AGGRO:
case LINKING_EVENT_EVADE: if (pMaster->IsControlledByPlayer())
if (!pMaster->isAlive()) return;
pMaster->Respawn();
break; if (pMaster->isInCombat())
case LINKING_EVENT_RESPAWN: pMaster->SetInCombatWith(pEnemy);
if (pMaster->isAlive()) else
SetFollowing(pSource, pMaster); pMaster->AI()->AttackStart(pEnemy);
} break;
case LINKING_EVENT_EVADE:
if (!pMaster->isAlive())
pMaster->Respawn();
break;
case LINKING_EVENT_RESPAWN:
if (pMaster->isAlive())
SetFollowing(pSource, pMaster);
} }
} }
} }

View file

@ -85,8 +85,8 @@ struct CreatureLinkingInfo
uint32 mapId; uint32 mapId;
uint32 masterId; uint32 masterId;
uint32 masterDBGuid; uint32 masterDBGuid;
uint16 linkingFlag; uint16 linkingFlag:16;
uint16 searchRange; uint16 searchRange:16;
}; };
/** /**
@ -121,12 +121,15 @@ class CreatureLinkingMgr
// Storage of Data: npc_entry_slave, (map, npc_entry_master, flag, master_db_guid[If Unique], search_range) // Storage of Data: npc_entry_slave, (map, npc_entry_master, flag, master_db_guid[If Unique], search_range)
CreatureLinkingMap m_creatureLinkingMap; CreatureLinkingMap m_creatureLinkingMap;
// Storage of Data: npc_guid_slave, (map, npc_guid_master, flag, master_db_guid, search_range)
CreatureLinkingMap m_creatureLinkingGuidMap;
// Lookup Storage for fast access: // Lookup Storage for fast access:
UNORDERED_SET<uint32> m_eventTriggers; // master UNORDERED_SET<uint32> m_eventTriggers; // master by entry
UNORDERED_SET<uint32> m_eventGuidTriggers; // master by guid
// Check-routine // Check-routine
bool IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingInfo* pInfo); bool IsLinkingEntryValid(uint32 slaveEntry, CreatureLinkingInfo* pInfo, bool byEntry);
}; };
/** /**
@ -158,15 +161,21 @@ class CreatureLinkingHolder
private: private:
typedef std::list<ObjectGuid> GuidList; typedef std::list<ObjectGuid> GuidList;
// Structure associated to a master // Structure associated to a master (entry case)
struct InfoAndGuids struct InfoAndGuids
{ {
uint16 linkingFlag; uint16 linkingFlag:16;
uint16 searchRange; uint16 searchRange:16;
GuidList linkedGuids; GuidList linkedGuids;
}; };
// Structure associated to a master (guid case)
struct InfoAndGuid
{
uint16 linkingFlag;
ObjectGuid linkedGuid;
};
typedef std::multimap<uint32 /*masterEntry*/, InfoAndGuids> HolderMap; typedef std::multimap<uint32 /*masterEntryOrGuid*/, InfoAndGuids> HolderMap;
typedef std::pair<HolderMap::iterator, HolderMap::iterator> HolderMapBounds; typedef std::pair<HolderMap::iterator, HolderMap::iterator> HolderMapBounds;
typedef std::multimap<uint32 /*Entry*/, ObjectGuid> BossGuidMap; typedef std::multimap<uint32 /*Entry*/, ObjectGuid> BossGuidMap;
typedef std::pair<BossGuidMap::iterator, BossGuidMap::iterator> BossGuidMapBounds; typedef std::pair<BossGuidMap::iterator, BossGuidMap::iterator> BossGuidMapBounds;
@ -180,8 +189,10 @@ class CreatureLinkingHolder
// Helper function to return if a slave is in range of a boss // Helper function to return if a slave is in range of a boss
bool IsSlaveInRangeOfBoss(Creature* pSlave, Creature* pBoss, uint16 searchRange); bool IsSlaveInRangeOfBoss(Creature* pSlave, Creature* pBoss, uint16 searchRange);
// Storage of Data (boss, flag) GuidList for action triggering // Storage of Data (boss, flag, searchRange, GuidList) for action triggering
HolderMap m_holderMap; HolderMap m_holderMap;
// Storage of Data (boss, flag, slave-guid)
HolderMap m_holderGuidMap;
// boss_entry, guid for reverse action triggering and check alive // boss_entry, guid for reverse action triggering and check alive
BossGuidMap m_masterGuid; BossGuidMap m_masterGuid;
}; };

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11993" #define REVISION_NR "11994"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_11785_02_characters_instance" #define REVISION_DB_CHARACTERS "required_11785_02_characters_instance"
#define REVISION_DB_MANGOS "required_11985_01_mangos_gameobject_template_scripts" #define REVISION_DB_MANGOS "required_11994_01_mangos_creature_linking"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__