mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[11994] Implement creature_linking by guid
This commit is contained in:
parent
74e3e55668
commit
d41974b38b
6 changed files with 258 additions and 73 deletions
|
|
@ -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`
|
||||||
--
|
--
|
||||||
|
|
|
||||||
13
sql/updates/11994_01_mangos_creature_linking.sql
Normal file
13
sql/updates/11994_01_mangos_creature_linking.sql
Normal 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';
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue