diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 74f8439c0..1e873c8e7 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -27,6 +27,7 @@ #include "QuestDef.h" #include "GossipDef.h" #include "Player.h" +#include "GameEventMgr.h" #include "PoolManager.h" #include "Opcodes.h" #include "Log.h" @@ -197,7 +198,7 @@ void Creature::RemoveCorpse() /** * change the entry of creature until respawn */ -bool Creature::InitEntry(uint32 Entry, const CreatureData *data ) +bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/ ) { CreatureInfo const *normalInfo = ObjectMgr::GetCreatureTemplate(Entry); if(!normalInfo) @@ -244,7 +245,7 @@ bool Creature::InitEntry(uint32 Entry, 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); @@ -268,7 +269,11 @@ bool Creature::InitEntry(uint32 Entry, 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) { if (cinfo->equipmentId == 0) LoadEquipment(normalInfo->equipmentId); // use default from normal template if diff does not have any @@ -294,9 +299,9 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData *data ) return true; } -bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data, bool preserveHPAndPower) +bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/, bool preserveHPAndPower /*=true*/) { - if (!InitEntry(Entry, data)) + if (!InitEntry(Entry, data, eventData)) return false; m_regenHealth = GetCreatureInfo()->RegenHealth; @@ -355,8 +360,12 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data, bo 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; @@ -686,14 +695,14 @@ bool Creature::AIM_Initialize() return true; } -bool Creature::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team, const CreatureData *data) +bool Creature::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team /*= TEAM_NONE*/, const CreatureData *data /*= NULL*/, GameEventCreatureData const* eventData /*= NULL*/) { MANGOS_ASSERT(map); SetMap(map); SetPhaseMask(phaseMask,false); //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) { @@ -1185,7 +1194,7 @@ float Creature::GetSpellDamageMod(int32 Rank) } } -bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, Team team, const CreatureData *data) +bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, Team team, const CreatureData *data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/) { CreatureInfo const *cinfo = ObjectMgr::GetCreatureTemplate(Entry); if(!cinfo) @@ -1197,7 +1206,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, Team team, const Cr Object::_Create(guidlow, Entry, HIGHGUID_UNIT); - if (!UpdateEntry(Entry, team, data, false)) + if (!UpdateEntry(Entry, team, data, eventData, false)) return false; return true; @@ -1213,6 +1222,8 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map) return false; } + GameEventCreatureData const* eventData = sGameEventMgr.GetCreatureUpdateDataForActiveEvent(guidlow); + m_DBTableGuid = guidlow; if (map->GetInstanceId() == 0) { @@ -1226,7 +1237,7 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map) else guidlow = sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT); - if (!Create(guidlow, map, data->phaseMask, data->id, TEAM_NONE, data)) + if (!Create(guidlow, map, data->phaseMask, data->id, TEAM_NONE, data, eventData)) return false; Relocate(data->posX, data->posY, data->posZ, data->orientation); diff --git a/src/game/Creature.h b/src/game/Creature.h index 83f7b68de..e5f59cd3e 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 @@ -397,7 +399,7 @@ class MANGOS_DLL_SPEC Creature : public Unit void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team = TEAM_NONE, const CreatureData *data = NULL); + bool Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team = TEAM_NONE, 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); @@ -499,7 +501,7 @@ class MANGOS_DLL_SPEC Creature : public Unit bool HasSpell(uint32 spellID) const; - bool UpdateEntry(uint32 entry, Team team = ALLIANCE, const CreatureData* data = NULL, bool preserveHPAndPower = true); + bool UpdateEntry(uint32 entry, Team team = ALLIANCE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL, bool preserveHPAndPower = true); bool UpdateStats(Stats stat); bool UpdateAllStats(); void UpdateResistances(uint32 school); @@ -522,7 +524,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; @@ -639,8 +641,8 @@ class MANGOS_DLL_SPEC Creature : public Unit void SendAreaSpiritHealerQueryOpcode(Player *pl); protected: - bool CreateFromProto(uint32 guidlow,uint32 Entry, Team team, const CreatureData *data = NULL); - bool InitEntry(uint32 entry, const CreatureData* data=NULL); + bool CreateFromProto(uint32 guidlow,uint32 Entry, Team team, const CreatureData *data = NULL, GameEventCreatureData const* eventData =NULL); + bool InitEntry(uint32 entry, 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 53d61ab85..6895930b5 100644 --- a/src/game/GameEventMgr.cpp +++ b/src/game/GameEventMgr.cpp @@ -343,7 +343,7 @@ 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 @@ -371,19 +371,17 @@ void GameEventMgr::LoadFromDB() uint32 guid = fields[0].GetUInt32(); uint16 event_id = fields[1].GetUInt16(); - if(event_id >= mGameEventModelEquip.size()) + if(event_id >= mGameEventCreatureData.size()) { sLog.outErrorDb("`game_event_model_equip` 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; + GameEventCreatureDataList& equiplist = mGameEventCreatureData[event_id]; + GameEventCreatureData 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) { @@ -394,7 +392,8 @@ void GameEventMgr::LoadFromDB() } } - equiplist.push_back(std::pair(guid, newModelEquipSet)); + equiplist.push_back(GameEventCreatureDataPair(guid, newModelEquipSet)); + mGameEventCreatureDataPerGuid[guid] = event_id; } while( result->NextRow() ); delete result; @@ -513,7 +512,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); UpdateWorldStates(event_id, false); @@ -531,7 +530,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); UpdateWorldStates(event_id, true); @@ -727,9 +726,26 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) } } -void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) + +GameEventCreatureData const* GameEventMgr::GetCreatureUpdateDataForActiveEvent(uint32 lowguid) const { - for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr) + // only for active event + GameEventCreatureDataPerGuidMap::const_iterator itr = mGameEventCreatureDataPerGuid.find(lowguid); + if (itr == mGameEventCreatureDataPerGuid.end() || !IsActiveEvent(itr->second)) + return NULL; + + uint32 event_id = itr->second; + + 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(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); @@ -738,67 +754,7 @@ 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, TEAM_NONE, data, activate ? &itr->second : NULL); } } diff --git a/src/game/GameEventMgr.h b/src/game/GameEventMgr.h index a35d70166..030e8a2a9 100644 --- a/src/game/GameEventMgr.h +++ b/src/game/GameEventMgr.h @@ -42,14 +42,14 @@ struct GameEventData bool isValid() const { return length > 0; } }; -struct ModelEquip +struct GameEventCreatureData { uint32 modelid; uint32 equipment_id; - uint32 modelid_prev; - uint32 equipement_id_prev; }; +typedef std::pair GameEventCreatureDataPair; + class GameEventMgr { public: @@ -63,12 +63,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); } @@ -76,7 +78,8 @@ 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); void UpdateWorldStates(uint16 event_id, bool Activate); protected: @@ -84,15 +87,17 @@ class GameEventMgr 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 UNORDERED_MAP GameEventCreatureDataPerGuidMap; 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/shared/revision_nr.h b/src/shared/revision_nr.h index 5a6f8a5a9..8baba655f 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 "10928" + #define REVISION_NR "10929" #endif // __REVISION_NR_H__