[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 "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);

View file

@ -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

View file

@ -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<uint32, ModelEquip>(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);
}
}

View file

@ -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<uint32, GameEventCreatureData> 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<typename T>
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<uint16> IdList;
typedef std::vector<GuidList> GameEventGuidMap;
typedef std::vector<IdList> GameEventIdMap;
typedef std::pair<uint32, ModelEquip> ModelEquipPair;
typedef std::list<ModelEquipPair> ModelEquipList;
typedef std::vector<ModelEquipList> GameEventModelEquipMap;
typedef std::list<GameEventCreatureDataPair> GameEventCreatureDataList;
typedef std::vector<GameEventCreatureDataList> GameEventCreatureDataMap;
typedef UNORDERED_MAP<uint32, uint32> GameEventCreatureDataPerGuidMap;
typedef std::list<uint32> QuestList;
typedef std::vector<QuestList> 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

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10928"
#define REVISION_NR "10929"
#endif // __REVISION_NR_H__