[10929] Move game event creature morphing code to Creature::UpdateEntry

* This is allow have more clean logic in feature work.
* Prevent modify static creature data.
This commit is contained in:
VladimirMangos 2010-12-28 20:34:49 +03:00
parent f8921dbca8
commit 3ff5ff2e6f
5 changed files with 72 additions and 98 deletions

View file

@ -27,6 +27,7 @@
#include "QuestDef.h" #include "QuestDef.h"
#include "GossipDef.h" #include "GossipDef.h"
#include "Player.h" #include "Player.h"
#include "GameEventMgr.h"
#include "PoolManager.h" #include "PoolManager.h"
#include "Opcodes.h" #include "Opcodes.h"
#include "Log.h" #include "Log.h"
@ -197,7 +198,7 @@ void Creature::RemoveCorpse()
/** /**
* change the entry of creature until respawn * 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); CreatureInfo const *normalInfo = ObjectMgr::GetCreatureTemplate(Entry);
if(!normalInfo) 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 // known valid are: CLASS_WARRIOR,CLASS_PALADIN,CLASS_ROGUE,CLASS_MAGE
SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); 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 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); 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); SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
// Load creature equipment // 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) if (cinfo->equipmentId == 0)
LoadEquipment(normalInfo->equipmentId); // use default from normal template if diff does not have any 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; 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; return false;
m_regenHealth = GetCreatureInfo()->RegenHealth; m_regenHealth = GetCreatureInfo()->RegenHealth;
@ -355,8 +360,12 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data, bo
return 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) // Use creature model explicit, override template (creature.modelid)
if (data && data->modelid_override) if (data && data->modelid_override)
return data->modelid_override; return data->modelid_override;
@ -686,14 +695,14 @@ bool Creature::AIM_Initialize()
return true; 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); MANGOS_ASSERT(map);
SetMap(map); SetMap(map);
SetPhaseMask(phaseMask,false); SetPhaseMask(phaseMask,false);
//oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; //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) 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); CreatureInfo const *cinfo = ObjectMgr::GetCreatureTemplate(Entry);
if(!cinfo) if(!cinfo)
@ -1197,7 +1206,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, Team team, const Cr
Object::_Create(guidlow, Entry, HIGHGUID_UNIT); Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
if (!UpdateEntry(Entry, team, data, false)) if (!UpdateEntry(Entry, team, data, eventData, false))
return false; return false;
return true; return true;
@ -1213,6 +1222,8 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map)
return false; return false;
} }
GameEventCreatureData const* eventData = sGameEventMgr.GetCreatureUpdateDataForActiveEvent(guidlow);
m_DBTableGuid = guidlow; m_DBTableGuid = guidlow;
if (map->GetInstanceId() == 0) if (map->GetInstanceId() == 0)
{ {
@ -1226,7 +1237,7 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map)
else else
guidlow = sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT); 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; return false;
Relocate(data->posX, data->posY, data->posZ, data->orientation); Relocate(data->posX, data->posY, data->posZ, data->orientation);

View file

@ -39,6 +39,8 @@ class Quest;
class Player; class Player;
class WorldSession; class WorldSession;
struct GameEventCreatureData;
enum CreatureFlagsExtra enum CreatureFlagsExtra
{ {
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group 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 AddToWorld();
void RemoveFromWorld(); 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); bool LoadCreatureAddon(bool reload = false);
void SelectLevel(const CreatureInfo *cinfo, float percentHealth = 100.0f, float percentMana = 100.0f); void SelectLevel(const CreatureInfo *cinfo, float percentHealth = 100.0f, float percentMana = 100.0f);
void LoadEquipment(uint32 equip_entry, bool force=false); 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 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 UpdateStats(Stats stat);
bool UpdateAllStats(); bool UpdateAllStats();
void UpdateResistances(uint32 school); void UpdateResistances(uint32 school);
@ -522,7 +524,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; }
CreatureDataAddon const* GetCreatureAddon() const; 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 GetAIName() const;
std::string GetScriptName() const; std::string GetScriptName() const;
@ -639,8 +641,8 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SendAreaSpiritHealerQueryOpcode(Player *pl); void SendAreaSpiritHealerQueryOpcode(Player *pl);
protected: protected:
bool CreateFromProto(uint32 guidlow,uint32 Entry, Team team, 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); bool InitEntry(uint32 entry, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL);
void RelocationNotify(); void RelocationNotify();
uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 m_groupLootTimer; // (msecs)timer used for group loot

View file

@ -343,7 +343,7 @@ void GameEventMgr::LoadFromDB()
sPoolMgr.CheckEventLinkAndReport(pool_id, event_id, creature2event, go2event); sPoolMgr.CheckEventLinkAndReport(pool_id, event_id, creature2event, go2event);
} }
mGameEventModelEquip.resize(mGameEvent.size()); mGameEventCreatureData.resize(mGameEvent.size());
// 0 1 2 // 0 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid," result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
// 3 // 3
@ -371,19 +371,17 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32(); uint32 guid = fields[0].GetUInt32();
uint16 event_id = fields[1].GetUInt16(); 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); 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; continue;
} }
++count; ++count;
ModelEquipList& equiplist = mGameEventModelEquip[event_id]; GameEventCreatureDataList& equiplist = mGameEventCreatureData[event_id];
ModelEquip newModelEquipSet; GameEventCreatureData newModelEquipSet;
newModelEquipSet.modelid = fields[2].GetUInt32(); newModelEquipSet.modelid = fields[2].GetUInt32();
newModelEquipSet.equipment_id = fields[3].GetUInt32(); newModelEquipSet.equipment_id = fields[3].GetUInt32();
newModelEquipSet.equipement_id_prev = 0;
newModelEquipSet.modelid_prev = 0;
if(newModelEquipSet.equipment_id > 0) if(newModelEquipSet.equipment_id > 0)
{ {
@ -394,7 +392,8 @@ void GameEventMgr::LoadFromDB()
} }
} }
equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet)); equiplist.push_back(GameEventCreatureDataPair(guid, newModelEquipSet));
mGameEventCreatureDataPerGuid[guid] = event_id;
} while( result->NextRow() ); } while( result->NextRow() );
delete result; delete result;
@ -513,7 +512,7 @@ void GameEventMgr::UnApplyEvent(uint16 event_id)
int16 event_nid = (-1) * event_id; int16 event_nid = (-1) * event_id;
GameEventSpawn(event_nid); GameEventSpawn(event_nid);
// restore equipment or model // restore equipment or model
ChangeEquipOrModel(event_id, false); UpdateCreatureData(event_id, false);
// Remove quests that are events only to non event npc // Remove quests that are events only to non event npc
UpdateEventQuests(event_id, false); UpdateEventQuests(event_id, false);
UpdateWorldStates(event_id, false); UpdateWorldStates(event_id, false);
@ -531,7 +530,7 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
int16 event_nid = (-1) * event_id; int16 event_nid = (-1) * event_id;
GameEventUnspawn(event_nid); GameEventUnspawn(event_nid);
// Change equipement or model // Change equipement or model
ChangeEquipOrModel(event_id, true); UpdateCreatureData(event_id, true);
// Add quests that are events only to non event npc // Add quests that are events only to non event npc
UpdateEventQuests(event_id, true); UpdateEventQuests(event_id, true);
UpdateWorldStates(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 // Remove the creature from grid
CreatureData const* data = sObjectMgr.GetCreatureData(itr->first); CreatureData const* data = sObjectMgr.GetCreatureData(itr->first);
@ -738,67 +754,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
// Update if spawned // Update if spawned
if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first))) if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first)))
{ pCreature->UpdateEntry(data->id, TEAM_NONE, data, activate ? &itr->second : NULL);
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;
}
} }
} }

View file

@ -42,14 +42,14 @@ struct GameEventData
bool isValid() const { return length > 0; } bool isValid() const { return length > 0; }
}; };
struct ModelEquip struct GameEventCreatureData
{ {
uint32 modelid; uint32 modelid;
uint32 equipment_id; uint32 equipment_id;
uint32 modelid_prev;
uint32 equipement_id_prev;
}; };
typedef std::pair<uint32, GameEventCreatureData> GameEventCreatureDataPair;
class GameEventMgr class GameEventMgr
{ {
public: public:
@ -63,12 +63,14 @@ class GameEventMgr
uint32 NextCheck(uint16 entry) const; uint32 NextCheck(uint16 entry) const;
void LoadFromDB(); void LoadFromDB();
uint32 Update(); 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(); uint32 Initialize();
void StartEvent(uint16 event_id, bool overwrite = false); void StartEvent(uint16 event_id, bool overwrite = false);
void StopEvent(uint16 event_id, bool overwrite = false); void StopEvent(uint16 event_id, bool overwrite = false);
template<typename T> template<typename T>
int16 GetGameEventId(uint32 guid_or_poolid); int16 GetGameEventId(uint32 guid_or_poolid);
GameEventCreatureData const* GetCreatureUpdateDataForActiveEvent(uint32 lowguid) const;
private: private:
void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); } void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); }
void RemoveActiveEvent(uint16 event_id) { m_ActiveEvents.erase(event_id); } void RemoveActiveEvent(uint16 event_id) { m_ActiveEvents.erase(event_id); }
@ -76,7 +78,8 @@ class GameEventMgr
void UnApplyEvent(uint16 event_id); void UnApplyEvent(uint16 event_id);
void GameEventSpawn(int16 event_id); void GameEventSpawn(int16 event_id);
void GameEventUnspawn(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 UpdateEventQuests(uint16 event_id, bool Activate);
void UpdateWorldStates(uint16 event_id, bool Activate); void UpdateWorldStates(uint16 event_id, bool Activate);
protected: protected:
@ -84,15 +87,17 @@ class GameEventMgr
typedef std::list<uint16> IdList; typedef std::list<uint16> IdList;
typedef std::vector<GuidList> GameEventGuidMap; typedef std::vector<GuidList> GameEventGuidMap;
typedef std::vector<IdList> GameEventIdMap; typedef std::vector<IdList> GameEventIdMap;
typedef std::pair<uint32, ModelEquip> ModelEquipPair; typedef std::list<GameEventCreatureDataPair> GameEventCreatureDataList;
typedef std::list<ModelEquipPair> ModelEquipList; typedef std::vector<GameEventCreatureDataList> GameEventCreatureDataMap;
typedef std::vector<ModelEquipList> GameEventModelEquipMap; typedef UNORDERED_MAP<uint32, uint32> GameEventCreatureDataPerGuidMap;
typedef std::list<uint32> QuestList; typedef std::list<uint32> QuestList;
typedef std::vector<QuestList> GameEventQuestMap; typedef std::vector<QuestList> GameEventQuestMap;
GameEventQuestMap mGameEventQuests; // events*2-1 GameEventQuestMap mGameEventQuests; // events*2-1
GameEventModelEquipMap mGameEventModelEquip; // events*2-1 GameEventCreatureDataMap mGameEventCreatureData; // events*2-1
GameEventCreatureDataPerGuidMap mGameEventCreatureDataPerGuid;
GameEventGuidMap mGameEventCreatureGuids; // events*2-1 GameEventGuidMap mGameEventCreatureGuids; // events*2-1
GameEventGuidMap mGameEventGameobjectGuids; // events*2-1 GameEventGuidMap mGameEventGameobjectGuids; // events*2-1
GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case

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 "10928" #define REVISION_NR "10929"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__