From aa8b61d083c35112d178cd719618f6da04bf3024 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 31 Dec 2010 19:35:47 +0300 Subject: [PATCH] [z1186] Imporvments gameevent creature morphing. * This is allow have more clean logic in feature work. * Prevent modify static creature data. * Table `game_event_model_equip` renamed to `game_event_creature_data` * Table allow now store same creatures for different events, BUT expected that related events no active in same time. * Added possibility switch entry at gameevent time. This let have diff factions/loot and etc for creatures. * Added possibility cast spells at gameevent start/end. Exist some spells that expected casted to creature at gameevent start for model replace, and for animation in other cases. Note: `game_event_creature_data`.`modelid` field posisble will removed soon in fowor related spell use. Ofc, when spells will implemented in core. (based on master commit cedf1d2) (based on master commit 36c0e42) (based on master commit af25119) (based on commit 43e4343) --- sql/mangos.sql | 51 +++--- sql/updates/Makefile.am | 6 +- ...600_01_mangos_game_event_creature_data.sql | 14 ++ src/game/Creature.cpp | 64 +++++-- src/game/Creature.h | 14 +- src/game/GameEventMgr.cpp | 168 +++++++++--------- src/game/GameEventMgr.h | 26 ++- src/game/SpellMgr.h | 18 ++ src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 10 files changed, 222 insertions(+), 143 deletions(-) create mode 100644 sql/updates/z1186_s0600_01_mangos_game_event_creature_data.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index cff0e2559..005c0ae3d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_z1159_s0566_01_mangos_mangos_string` bit(1) default NULL + `required_z1186_s0600_01_mangos_game_event_creature_data` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1579,51 +1579,52 @@ LOCK TABLES `game_event_creature` WRITE; UNLOCK TABLES; -- --- Table structure for table `game_event_gameobject` +-- Table structure for table `game_event_creature_data` -- -DROP TABLE IF EXISTS `game_event_gameobject`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `game_event_gameobject` ( - `guid` int(10) unsigned NOT NULL, - `event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.', - PRIMARY KEY (`guid`) +DROP TABLE IF EXISTS `game_event_creature_data`; +CREATE TABLE `game_event_creature_data` ( + `guid` int(10) unsigned NOT NULL default '0', + `entry_id` mediumint(8) unsigned NOT NULL default '0', + `modelid` mediumint(8) unsigned NOT NULL default '0', + `equipment_id` mediumint(8) unsigned NOT NULL default '0', + `spell_start` mediumint(8) unsigned NOT NULL default '0', + `spell_end` mediumint(8) unsigned NOT NULL default '0', + `event` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`guid`,`event`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `game_event_gameobject` +-- Dumping data for table `game_event_creature_data` -- -LOCK TABLES `game_event_gameobject` WRITE; -/*!40000 ALTER TABLE `game_event_gameobject` DISABLE KEYS */; -/*!40000 ALTER TABLE `game_event_gameobject` ENABLE KEYS */; +LOCK TABLES `game_event_creature_data` WRITE; +/*!40000 ALTER TABLE `game_event_creature_data` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_creature_data` ENABLE KEYS */; UNLOCK TABLES; -- --- Table structure for table `game_event_model_equip` +-- Table structure for table `game_event_gameobject` -- -DROP TABLE IF EXISTS `game_event_model_equip`; +DROP TABLE IF EXISTS `game_event_gameobject`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `game_event_model_equip` ( - `guid` int(10) unsigned NOT NULL DEFAULT '0', - `modelid` mediumint(8) unsigned NOT NULL DEFAULT '0', - `equipment_id` mediumint(8) unsigned NOT NULL DEFAULT '0', - `event` smallint(5) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`guid`) +CREATE TABLE `game_event_gameobject` ( + `guid` int(10) unsigned NOT NULL, + `event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.', + PRIMARY KEY (`guid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `game_event_model_equip` +-- Dumping data for table `game_event_gameobject` -- -LOCK TABLES `game_event_model_equip` WRITE; -/*!40000 ALTER TABLE `game_event_model_equip` DISABLE KEYS */; -/*!40000 ALTER TABLE `game_event_model_equip` ENABLE KEYS */; +LOCK TABLES `game_event_gameobject` WRITE; +/*!40000 ALTER TABLE `game_event_gameobject` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_gameobject` ENABLE KEYS */; UNLOCK TABLES; -- diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 3c973e2d6..fc6a7d722 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -188,7 +188,8 @@ pkgdata_DATA = \ z1135_s0540_02_characters_character_spell.sql \ z1135_xxxxx_03_mangos_playercreateinfo_spell.sql \ z1142_s0531_01_characters_bugreport.sql \ - z1159_s0566_01_mangos_mangos_string.sql + z1159_s0566_01_mangos_mangos_string.sql \ + z1186_s0600_01_mangos_game_event_creature_data.sql ## Additional files to include when running 'make dist' # SQL update files, to upgrade database schema from older revisions @@ -355,4 +356,5 @@ EXTRA_DIST = \ z1135_s0540_02_characters_character_spell.sql \ z1135_xxxxx_03_mangos_playercreateinfo_spell.sql \ z1142_s0531_01_characters_bugreport.sql \ - z1159_s0566_01_mangos_mangos_string.sql + z1159_s0566_01_mangos_mangos_string.sql \ + z1186_s0600_01_mangos_game_event_creature_data.sql diff --git a/sql/updates/z1186_s0600_01_mangos_game_event_creature_data.sql b/sql/updates/z1186_s0600_01_mangos_game_event_creature_data.sql new file mode 100644 index 000000000..76f7a09a9 --- /dev/null +++ b/sql/updates/z1186_s0600_01_mangos_game_event_creature_data.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_z1159_s0566_01_mangos_mangos_string required_z1186_s0600_01_mangos_game_event_creature_data bit; + + +DROP TABLE IF EXISTS game_event_creature_data; +RENAME TABLE game_event_model_equip TO game_event_creature_data; + +ALTER TABLE game_event_creature_data + ADD COLUMN entry_id mediumint(8) unsigned NOT NULL default '0' AFTER guid, + ADD COLUMN spell_start mediumint(8) unsigned NOT NULL default '0' AFTER equipment_id, + ADD COLUMN spell_end mediumint(8) unsigned NOT NULL default '0' AFTER spell_start; + +ALTER TABLE game_event_creature_data + DROP PRIMARY KEY, + ADD PRIMARY KEY (`guid`,`event`); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 9988f402c..5d8e42eea 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -28,6 +28,7 @@ #include "QuestDef.h" #include "GossipDef.h" #include "Player.h" +#include "GameEventMgr.h" #include "PoolManager.h" #include "Opcodes.h" #include "Log.h" @@ -201,8 +202,12 @@ void Creature::RemoveCorpse() /** * change the entry of creature until respawn */ -bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) +bool Creature::InitEntry(uint32 Entry, uint32 team, CreatureData const* data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/ ) { + // use game event entry if any instead default suggested + if (eventData && eventData->entry_id) + Entry = eventData->entry_id; + CreatureInfo const *normalInfo = ObjectMgr::GetCreatureTemplate(Entry); if(!normalInfo) { @@ -223,7 +228,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) // known valid are: CLASS_WARRIOR,CLASS_PALADIN,CLASS_ROGUE,CLASS_MAGE SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); - uint32 display_id = ChooseDisplayId(GetCreatureInfo(), data); + uint32 display_id = ChooseDisplayId(GetCreatureInfo(), data, eventData); if (!display_id) // Cancel load if no display id { sLog.outErrorDb("Creature (Entry: %u) has no model defined in table `creature_template`, can't load.", Entry); @@ -254,7 +259,11 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); // Load creature equipment - if(!data || data->equipmentId == 0) + if (eventData && eventData->equipment_id) + { + LoadEquipment(eventData->equipment_id); // use event equipment if any for active event + } + else if (!data || data->equipmentId == 0) { // use default from the template LoadEquipment(cinfo->equipmentId); } @@ -277,9 +286,9 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data ) return true; } -bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data, bool preserveHPAndPower) +bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/, bool preserveHPAndPower /*=true*/) { - if (!InitEntry(Entry, team, data)) + if (!InitEntry(Entry, team, data, eventData)) return false; m_regenHealth = GetCreatureInfo()->RegenHealth; @@ -337,11 +346,19 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data, for(int i = 0; i < CREATURE_MAX_SPELLS; ++i) m_spells[i] = GetCreatureInfo()->spells[i]; + // if eventData set then event active and need apply spell_start + if (eventData) + ApplyGameEventSpells(eventData, true); + return true; } -uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *data /*= NULL*/) +uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *data /*= NULL*/, GameEventCreatureData const* eventData /*=NULL*/) { + // Use creature event model explicit, override any other static models + if (eventData && eventData->modelid) + return eventData->modelid; + // Use creature model explicit, override template (creature.modelid) if (data && data->modelid_override) return data->modelid_override; @@ -401,7 +418,11 @@ void Creature::Update(uint32 diff) lootForSkin = false; if(m_originalEntry != GetEntry()) - UpdateEntry(m_originalEntry); + { + // need preserver gameevent state + GameEventCreatureData const* eventData = sGameEventMgr.GetCreatureUpdateDataForActiveEvent(GetDBTableGUIDLow()); + UpdateEntry(m_originalEntry, 0, NULL, eventData); + } CreatureInfo const *cinfo = GetCreatureInfo(); @@ -652,13 +673,13 @@ bool Creature::AIM_Initialize() return true; } -bool Creature::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data) +bool Creature::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data /*= NULL*/, GameEventCreatureData const* eventData /*= NULL*/) { MANGOS_ASSERT(map); SetMap(map); //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; - const bool bResult = CreateFromProto(guidlow, Entry, team, data); + const bool bResult = CreateFromProto(guidlow, Entry, team, data, eventData); if (bResult) { @@ -1126,7 +1147,7 @@ float Creature::GetSpellDamageMod(int32 Rank) } } -bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const CreatureData *data) +bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const CreatureData *data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/) { CreatureInfo const *cinfo = ObjectMgr::GetCreatureTemplate(Entry); if(!cinfo) @@ -1138,7 +1159,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const Object::_Create(guidlow, Entry, HIGHGUID_UNIT); - if (!UpdateEntry(Entry, team, data, false)) + if (!UpdateEntry(Entry, team, data, eventData, false)) return false; return true; @@ -1154,6 +1175,8 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map) return false; } + GameEventCreatureData const* eventData = sGameEventMgr.GetCreatureUpdateDataForActiveEvent(guidlow); + m_DBTableGuid = guidlow; if (map->GetInstanceId() == 0) { @@ -1167,8 +1190,7 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map) else guidlow = sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT); - uint16 team = 0; - if (!Create(guidlow, map, data->id, team, data)) + if (!Create(guidlow, map, data->id, 0, data, eventData)) return false; Relocate(data->posX, data->posY, data->posZ, data->orientation); @@ -1290,7 +1312,7 @@ void Creature::DeleteFromDB() WorldDatabase.PExecuteLog("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.PExecuteLog("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.PExecuteLog("DELETE FROM game_event_creature_data WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.PExecuteLog("DELETE FROM creature_battleground WHERE guid = '%u'", m_DBTableGuid); WorldDatabase.CommitTransaction(); } @@ -2261,3 +2283,17 @@ void Creature::RelocationNotify() float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO); Cell::VisitAllObjects(this, relocationNotifier, radius); } + +void Creature::ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated) +{ + uint32 cast_spell = activated ? eventData->spell_id_start : eventData->spell_id_end; + uint32 remove_spell = activated ? eventData->spell_id_end : eventData->spell_id_start; + + if (remove_spell) + if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(remove_spell)) + if (IsSpellAppliesAura(spellEntry)) + RemoveAurasDueToSpell(remove_spell); + + if (cast_spell) + CastSpell(this, cast_spell, true); +} diff --git a/src/game/Creature.h b/src/game/Creature.h index e7d168d61..b7feff6a1 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -39,6 +39,8 @@ class Quest; class Player; class WorldSession; +struct GameEventCreatureData; + enum CreatureFlagsExtra { CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group @@ -367,7 +369,7 @@ class MANGOS_DLL_SPEC Creature : public Unit void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data = NULL); + bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data = NULL, GameEventCreatureData const* eventData = NULL); bool LoadCreatureAddon(bool reload = false); void SelectLevel(const CreatureInfo *cinfo, float percentHealth = 100.0f, float percentMana = 100.0f); void LoadEquipment(uint32 equip_entry, bool force=false); @@ -468,7 +470,9 @@ class MANGOS_DLL_SPEC Creature : public Unit bool HasSpell(uint32 spellID) const; - bool UpdateEntry(uint32 entry, uint32 team = ALLIANCE, const CreatureData* data = NULL, bool preserveHPAndPower = true); + bool UpdateEntry(uint32 entry, uint32 team = ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL, bool preserveHPAndPower = true); + + void ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated); bool UpdateStats(Stats stat); bool UpdateAllStats(); void UpdateResistances(uint32 school); @@ -491,7 +495,7 @@ class MANGOS_DLL_SPEC Creature : public Unit CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } CreatureDataAddon const* GetCreatureAddon() const; - static uint32 ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *data = NULL); + static uint32 ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *data = NULL, GameEventCreatureData const* eventData = NULL); std::string GetAIName() const; std::string GetScriptName() const; @@ -608,8 +612,8 @@ class MANGOS_DLL_SPEC Creature : public Unit void SendAreaSpiritHealerQueryOpcode(Player *pl); protected: - bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); - bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); + bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL, GameEventCreatureData const* eventData =NULL); + bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); void RelocationNotify(); uint32 m_groupLootTimer; // (msecs)timer used for group loot diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp index 34e4bc02d..5cfa491c2 100644 --- a/src/game/GameEventMgr.cpp +++ b/src/game/GameEventMgr.cpp @@ -27,6 +27,7 @@ #include "Log.h" #include "MapManager.h" #include "BattleGroundMgr.h" +#include "SpellMgr.h" #include "Policies/SingletonImp.h" INSTANTIATE_SINGLETON_1(GameEventMgr); @@ -334,12 +335,14 @@ void GameEventMgr::LoadFromDB() sPoolMgr.CheckEventLinkAndReport(pool_id, event_id, creature2event, go2event); } - mGameEventModelEquip.resize(mGameEvent.size()); + mGameEventCreatureData.resize(mGameEvent.size()); // 0 1 2 - result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid," - // 3 - "game_event_model_equip.equipment_id " - "FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid"); + result = WorldDatabase.Query("SELECT creature.guid, game_event_creature_data.event, game_event_creature_data.modelid," + // 3 4 + "game_event_creature_data.equipment_id, game_event_creature_data.entry_id, " + // 5 6 + "game_event_creature_data.spell_start, game_event_creature_data.spell_end " + "FROM creature JOIN game_event_creature_data ON creature.guid=game_event_creature_data.guid"); count = 0; if( !result ) @@ -348,7 +351,7 @@ void GameEventMgr::LoadFromDB() bar.step(); sLog.outString(); - sLog.outString(">> Loaded %u model/equipment changes in game events", count ); + sLog.outString(">> Loaded %u creature reactions at game events", count ); } else { @@ -362,36 +365,59 @@ void GameEventMgr::LoadFromDB() uint32 guid = fields[0].GetUInt32(); uint16 event_id = fields[1].GetUInt16(); - if(event_id >= mGameEventModelEquip.size()) + if(event_id==0) { - sLog.outErrorDb("`game_event_model_equip` game event id (%u) is out of range compared to max event id in `game_event`",event_id); + sLog.outErrorDb("`game_event_creature_data` game event id (%i) is reserved and can't be used.",event_id); + continue; + } + + if(event_id >= mGameEventCreatureData.size()) + { + sLog.outErrorDb("`game_event_creature_data` game event id (%u) is out of range compared to max event id in `game_event`",event_id); continue; } ++count; - ModelEquipList& equiplist = mGameEventModelEquip[event_id]; - ModelEquip newModelEquipSet; - newModelEquipSet.modelid = fields[2].GetUInt32(); - newModelEquipSet.equipment_id = fields[3].GetUInt32(); - newModelEquipSet.equipement_id_prev = 0; - newModelEquipSet.modelid_prev = 0; - - if(newModelEquipSet.equipment_id > 0) + GameEventCreatureDataList& equiplist = mGameEventCreatureData[event_id]; + GameEventCreatureData newData; + newData.modelid = fields[2].GetUInt32(); + newData.equipment_id = fields[3].GetUInt32(); + newData.entry_id = fields[4].GetUInt32(); + newData.spell_id_start = fields[5].GetUInt32(); + newData.spell_id_end = fields[6].GetUInt32(); + + if (newData.equipment_id && !sObjectMgr.GetEquipmentInfo(newData.equipment_id)) { - if(!sObjectMgr.GetEquipmentInfo(newModelEquipSet.equipment_id)) - { - sLog.outErrorDb("Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newModelEquipSet.equipment_id); - continue; - } + sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newData.equipment_id); + newData.equipment_id = 0; + } + + if (newData.entry_id && !sObjectMgr.GetCreatureTemplate(newData.entry_id)) + { + sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with event time entry %u not found in table `creature_template`, set to no 0.", guid, newData.entry_id); + newData.entry_id = 0; } - equiplist.push_back(std::pair(guid, newModelEquipSet)); + if (newData.spell_id_start && !sSpellStore.LookupEntry(newData.spell_id_start)) + { + sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with nonexistent spell_start %u, set to no start spell.", guid, newData.spell_id_start); + newData.spell_id_start = 0; + } + + if (newData.spell_id_end && !sSpellStore.LookupEntry(newData.spell_id_end)) + { + sLog.outErrorDb("Table `game_event_creature_data` have creature (Guid: %u) with nonexistent spell_end %u, set to no end spell.", guid, newData.spell_id_end); + newData.spell_id_end = 0; + } + + equiplist.push_back(GameEventCreatureDataPair(guid, newData)); + mGameEventCreatureDataPerGuid.insert(GameEventCreatureDataPerGuidMap::value_type(guid, event_id)); } while( result->NextRow() ); delete result; sLog.outString(); - sLog.outString( ">> Loaded %u model/equipment changes in game events", count ); + sLog.outString(">> Loaded %u creature reactions at game events", count ); } mGameEventQuests.resize(mGameEvent.size()); @@ -503,7 +529,7 @@ void GameEventMgr::UnApplyEvent(uint16 event_id) int16 event_nid = (-1) * event_id; GameEventSpawn(event_nid); // restore equipment or model - ChangeEquipOrModel(event_id, false); + UpdateCreatureData(event_id, false); // Remove quests that are events only to non event npc UpdateEventQuests(event_id, false); } @@ -520,7 +546,7 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id) int16 event_nid = (-1) * event_id; GameEventUnspawn(event_nid); // Change equipement or model - ChangeEquipOrModel(event_id, true); + UpdateCreatureData(event_id, true); // Add quests that are events only to non event npc UpdateEventQuests(event_id, true); } @@ -711,9 +737,33 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) } } -void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) +GameEventCreatureData const* GameEventMgr::GetCreatureUpdateDataForActiveEvent(uint32 lowguid) const +{ + // only for active event, creature can be listed for many so search all + uint32 event_id = 0; + GameEventCreatureDataPerGuidBounds bounds = mGameEventCreatureDataPerGuid.equal_range(lowguid); + for(GameEventCreatureDataPerGuidMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr) + { + if (IsActiveEvent(itr->second)) + { + event_id = itr->second; + break; + } + } + + if (!event_id) + return NULL; + + for(GameEventCreatureDataList::const_iterator itr = mGameEventCreatureData[event_id].begin();itr != mGameEventCreatureData[event_id].end();++itr) + if (itr->first == lowguid) + return &itr->second; + + return NULL; +} + +void GameEventMgr::UpdateCreatureData(int16 event_id, bool activate) { - for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr) + for(GameEventCreatureDataList::iterator itr = mGameEventCreatureData[event_id].begin();itr != mGameEventCreatureData[event_id].end();++itr) { // Remove the creature from grid CreatureData const* data = sObjectMgr.GetCreatureData(itr->first); @@ -723,65 +773,11 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) // Update if spawned if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first))) { - if (activate) - { - itr->second.equipement_id_prev = pCreature->GetCurrentEquipmentId(); - itr->second.modelid_prev = pCreature->GetDisplayId(); - pCreature->LoadEquipment(itr->second.equipment_id, true); - if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid) - { - CreatureModelInfo const *minfo = sObjectMgr.GetCreatureModelInfo(itr->second.modelid); - if (minfo) - { - pCreature->SetDisplayId(itr->second.modelid); - pCreature->SetNativeDisplayId(itr->second.modelid); - } - } - } - else - { - pCreature->LoadEquipment(itr->second.equipement_id_prev, true); - if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid) - { - CreatureModelInfo const *minfo = sObjectMgr.GetCreatureModelInfo(itr->second.modelid_prev); - if (minfo) - { - pCreature->SetDisplayId(itr->second.modelid_prev); - pCreature->SetNativeDisplayId(itr->second.modelid_prev); - } - } - } - } - else // If not spawned - { - CreatureData const* data2 = sObjectMgr.GetCreatureData(itr->first); - if (data2 && activate) - { - CreatureInfo const *cinfo = ObjectMgr::GetCreatureTemplate(data2->id); - uint32 display_id = Creature::ChooseDisplayId(cinfo,data2); - CreatureModelInfo const *minfo = sObjectMgr.GetCreatureModelRandomGender(display_id); - if (minfo) - display_id = minfo->modelid; - - if (data2->equipmentId == 0) - itr->second.equipement_id_prev = cinfo->equipmentId; - else if (data2->equipmentId != -1) - itr->second.equipement_id_prev = data->equipmentId; - itr->second.modelid_prev = display_id; - } - } - // now last step: put in data - // just to have write access to it - CreatureData& data2 = sObjectMgr.NewOrExistCreatureData(itr->first); - if (activate) - { - data2.modelid_override = itr->second.modelid; - data2.equipmentId = itr->second.equipment_id; - } - else - { - data2.modelid_override = itr->second.modelid_prev; - data2.equipmentId = itr->second.equipement_id_prev; + pCreature->UpdateEntry(data->id, 0, data, activate ? &itr->second : NULL); + + // spells not casted for event remove case (sent NULL into update), do it + if (!activate) + pCreature->ApplyGameEventSpells(&itr->second, false); } } } diff --git a/src/game/GameEventMgr.h b/src/game/GameEventMgr.h index d3cac0ead..e642d6499 100644 --- a/src/game/GameEventMgr.h +++ b/src/game/GameEventMgr.h @@ -43,14 +43,17 @@ struct GameEventData bool isValid() const { return length > 0; } }; -struct ModelEquip +struct GameEventCreatureData { + uint32 entry_id; uint32 modelid; uint32 equipment_id; - uint32 modelid_prev; - uint32 equipement_id_prev; + uint32 spell_id_start; + uint32 spell_id_end; }; +typedef std::pair GameEventCreatureDataPair; + class GameEventMgr { public: @@ -64,12 +67,14 @@ class GameEventMgr uint32 NextCheck(uint16 entry) const; void LoadFromDB(); uint32 Update(); - bool IsActiveEvent(uint16 event_id) { return ( m_ActiveEvents.find(event_id)!=m_ActiveEvents.end()); } + bool IsActiveEvent(uint16 event_id) const { return ( m_ActiveEvents.find(event_id)!=m_ActiveEvents.end()); } uint32 Initialize(); void StartEvent(uint16 event_id, bool overwrite = false); void StopEvent(uint16 event_id, bool overwrite = false); template int16 GetGameEventId(uint32 guid_or_poolid); + + GameEventCreatureData const* GetCreatureUpdateDataForActiveEvent(uint32 lowguid) const; private: void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); } void RemoveActiveEvent(uint16 event_id) { m_ActiveEvents.erase(event_id); } @@ -77,22 +82,25 @@ class GameEventMgr void UnApplyEvent(uint16 event_id); void GameEventSpawn(int16 event_id); void GameEventUnspawn(int16 event_id); - void ChangeEquipOrModel(int16 event_id, bool activate); + void UpdateCreatureData(int16 event_id, bool activate); void UpdateEventQuests(uint16 event_id, bool Activate); protected: typedef std::list GuidList; typedef std::list IdList; typedef std::vector GameEventGuidMap; typedef std::vector GameEventIdMap; - typedef std::pair ModelEquipPair; - typedef std::list ModelEquipList; - typedef std::vector GameEventModelEquipMap; + typedef std::list GameEventCreatureDataList; + typedef std::vector GameEventCreatureDataMap; + typedef std::multimap GameEventCreatureDataPerGuidMap; + typedef std::pair GameEventCreatureDataPerGuidBounds; typedef std::list QuestList; typedef std::vector GameEventQuestMap; GameEventQuestMap mGameEventQuests; // events*2-1 - GameEventModelEquipMap mGameEventModelEquip; // events*2-1 + GameEventCreatureDataMap mGameEventCreatureData; // events*2-1 + GameEventCreatureDataPerGuidMap mGameEventCreatureDataPerGuid; + GameEventGuidMap mGameEventCreatureGuids; // events*2-1 GameEventGuidMap mGameEventGameobjectGuids; // events*2-1 GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 8e7969c52..22e4749e8 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -105,6 +105,24 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) return false; } +inline bool IsSpellAppliesAura(SpellEntry const *spellInfo, uint32 effectMask = ((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2))) +{ + for(int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (effectMask & (1 << i)) + { + switch (spellInfo->Effect[i]) + { + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + return true; + } + } + } + return false; +} + inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura) { for(int i = 0; i < MAX_EFFECT_INDEX; ++i) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2854010b3..e3d32ff15 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "1185" + #define REVISION_NR "1186" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 79494e993..18f6035b1 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_z1142_s0531_01_characters_bugreport" - #define REVISION_DB_MANGOS "required_z1159_s0566_01_mangos_mangos_string" + #define REVISION_DB_MANGOS "required_z1186_s0600_01_mangos_game_event_creature_data" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__