* Removed the misdesigned on_events script/hooks. * Lots of related cleanups and assertions. * The interface is now fully object-oriented. ** Scripts no longer use function pointers. ** Scripts no longer use the general-purpose Script struct for everything. ** Script types are split into separate classes which must be inherited depending on what functionality is desired. * Several script types have been added to allow extending functionality in a code-only manner (some script types require assignment in the recently added ScriptName columns in the database, though). ** SpellHandlerScript: Wrapper around spell scripts (returns new SpellScript objects (`spell_script_names`.`ScriptName`)). ** ServerScript: Allows scripting events that occur in the network layer. ** WorldScript: Allows scripting certain world-global events. ** FormulaScript: Allows hooking and interfering with core formulas. ** *MapScript: Allows hooking different map types (including world, instance, and battleground maps (`instance_template`.`ScriptName`)). ** ItemScript: Allows scripting of items (like the old interface (`item_template`.`ScriptName`)). ** CreatureScript: Allows scripting of creatures/AI (like the old interface (`creature_template`.`ScriptName`)). ** GameObjectScript: Allows scripting of gameobjects (like the old interface (`gameobject_template`.`ScriptName`)). ** AreaTriggerScript: Allows scripting triggered area triggers (like the old interface (`areatrigger_scripts`.`ScriptName`)). ** OutdoorPvPScript: Script which should return OutdoorPvP objects for use by OutdoorPvPMgr (`outdoorpvp_template`.`ScriptName`). ** CommandScript: Allows extending the in-core command table. ** WeatherScript: Allows scripting of weather changes (`game_weather`.`ScriptName`). ** AuctionHouseScript: Allows scripting of auction events. ** ConditionScript: Allows scripting of conditions (`conditions`.`ScriptName`). ** DynamicObjectScript: Allows scripting of dynamicobjects. ** TransportScript: Allows scripting of transport events (`transports`.`ScriptName`). * OutdoorPvP objects are now created through scripts. This effectively means that they'll need to be moved to scripts before the they're functional again. * The whole idea with this new interface is to allow expanding core functionality without touching core code. If further hooks are needed to expand functionality of the core, let us know; we'll add them, if we agree that it is appropriate to do so. *** NOTE: The scripts project will _not_ build before it has been adapted to the new interface. *** Thanks to everyone who helped out with related preparations and suggestions! --HG-- branch : trunk
1217 lines
36 KiB
C++
1217 lines
36 KiB
C++
/* Copyright (C) 2006 - 2008 TrinityScript <https://scriptdev2.svn.sourceforge.net/>
|
|
* This program is free software licensed under GPL version 2
|
|
* Please see the included DOCS/LICENSE.TXT for more information */
|
|
|
|
#include "ScriptPCH.h"
|
|
#include "Config.h"
|
|
#include "DatabaseEnv.h"
|
|
#include "DBCStores.h"
|
|
#include "ObjectMgr.h"
|
|
#include "ProgressBar.h"
|
|
#include "ScriptLoader.h"
|
|
#include "ScriptSystem.h"
|
|
|
|
// Utility macros to refer to the script registry.
|
|
#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptMap
|
|
#define SCR_REG_LST(T) ScriptRegistry<T>::ScriptPointerList
|
|
|
|
// Utility macros for looping over scripts.
|
|
#define FOR_SCRIPTS(T,C,E) \
|
|
if (SCR_REG_LST(T).empty()) \
|
|
return; \
|
|
for (SCR_REG_MAP(T)::iterator C = SCR_REG_LST(T).begin(); \
|
|
C != SCR_REG_LST(T).end(); ++C)
|
|
#define FOR_SCRIPTS_RET(T,C,E,R) \
|
|
if (SCR_REG_LST(T).empty()) \
|
|
return R; \
|
|
for (SCR_REG_MAP(T)::iterator C = SCR_REG_LST(T).begin(); \
|
|
C != SCR_REG_LST(T).end(); ++C)
|
|
#define FOREACH_SCRIPT(T) \
|
|
FOR_SCRIPTS(T, itr, end) \
|
|
itr->second
|
|
|
|
// Utility macros for finding specific scripts.
|
|
#define GET_SCRIPT(T,I,V) \
|
|
T* V = ScriptRegistry<T>::GetScriptById(I); \
|
|
if (!V) \
|
|
return;
|
|
#define GET_SCRIPT_RET(T,I,V,R) \
|
|
T* V = ScriptRegistry<T>::GetScriptById(I); \
|
|
if (!V) \
|
|
return R;
|
|
|
|
void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
|
|
{
|
|
if (!pSource)
|
|
{
|
|
sLog.outError("TSCR: DoScriptText entry %i, invalid Source pointer.", iTextEntry);
|
|
return;
|
|
}
|
|
|
|
if (iTextEntry >= 0)
|
|
{
|
|
sLog.outError("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
|
|
return;
|
|
}
|
|
|
|
const StringTextData* pData = sScriptSystemMgr.GetTextData(iTextEntry);
|
|
|
|
if (!pData)
|
|
{
|
|
sLog.outError("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
|
|
return;
|
|
}
|
|
|
|
sLog.outDebug("TSCR: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", iTextEntry, pData->uiSoundId, pData->uiType, pData->uiLanguage, pData->uiEmote);
|
|
|
|
if (pData->uiSoundId)
|
|
{
|
|
if (GetSoundEntriesStore()->LookupEntry(pData->uiSoundId))
|
|
pSource->SendPlaySound(pData->uiSoundId, false);
|
|
else
|
|
sLog.outError("TSCR: DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
|
|
}
|
|
|
|
if (pData->uiEmote)
|
|
{
|
|
if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER)
|
|
((Unit*)pSource)->HandleEmoteCommand(pData->uiEmote);
|
|
else
|
|
sLog.outError("TSCR: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId());
|
|
}
|
|
|
|
switch (pData->uiType)
|
|
{
|
|
case CHAT_TYPE_SAY:
|
|
pSource->MonsterSay(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
|
|
break;
|
|
case CHAT_TYPE_YELL:
|
|
pSource->MonsterYell(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
|
|
break;
|
|
case CHAT_TYPE_TEXT_EMOTE:
|
|
pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0);
|
|
break;
|
|
case CHAT_TYPE_BOSS_EMOTE:
|
|
pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0, true);
|
|
break;
|
|
case CHAT_TYPE_WHISPER:
|
|
{
|
|
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
|
|
pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID());
|
|
else
|
|
sLog.outError("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
|
|
|
|
break;
|
|
}
|
|
case CHAT_TYPE_BOSS_WHISPER:
|
|
{
|
|
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
|
|
pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID(), true);
|
|
else
|
|
sLog.outError("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
|
|
|
|
break;
|
|
}
|
|
case CHAT_TYPE_ZONE_YELL:
|
|
pSource->MonsterYellToZone(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ScriptMgr::ScriptMgr()
|
|
{
|
|
}
|
|
|
|
ScriptMgr::~ScriptMgr()
|
|
{
|
|
#define SCR_CLEAR(T) \
|
|
FOR_SCRIPTS(T, itr, end) \
|
|
delete itr->second; \
|
|
SCR_REG_LST(T).clear();
|
|
|
|
// Clear scripts for every script type.
|
|
SCR_CLEAR(SpellHandlerScript);
|
|
SCR_CLEAR(AuraHandlerScript);
|
|
SCR_CLEAR(ServerScript);
|
|
SCR_CLEAR(WorldScript);
|
|
SCR_CLEAR(FormulaScript);
|
|
SCR_CLEAR(WorldMapScript);
|
|
SCR_CLEAR(InstanceMapScript);
|
|
SCR_CLEAR(BattlegroundMapScript);
|
|
SCR_CLEAR(ItemScript);
|
|
SCR_CLEAR(CreatureScript);
|
|
SCR_CLEAR(GameObjectScript);
|
|
SCR_CLEAR(AreaTriggerScript);
|
|
SCR_CLEAR(BattlegroundScript);
|
|
SCR_CLEAR(OutdoorPvPScript);
|
|
SCR_CLEAR(CommandScript);
|
|
SCR_CLEAR(WeatherScript);
|
|
SCR_CLEAR(AuctionHouseScript);
|
|
SCR_CLEAR(ConditionScript);
|
|
SCR_CLEAR(VehicleScript);
|
|
SCR_CLEAR(DynamicObjectScript);
|
|
SCR_CLEAR(TransportScript);
|
|
|
|
#undef SCR_CLEAR
|
|
}
|
|
|
|
void ScriptMgr::Initialize()
|
|
{
|
|
LoadDatabase();
|
|
|
|
sLog.outString("Loading C++ scripts");
|
|
barGoLink bar(1);
|
|
bar.step();
|
|
sLog.outString("");
|
|
|
|
FillSpellSummary();
|
|
AddScripts();
|
|
|
|
sLog.outString(">> Loaded %u C++ scripts", GetScriptCount());
|
|
}
|
|
|
|
void ScriptMgr::LoadDatabase()
|
|
{
|
|
sScriptSystemMgr.LoadVersion();
|
|
sScriptSystemMgr.LoadScriptTexts();
|
|
sScriptSystemMgr.LoadScriptTextsCustom();
|
|
sScriptSystemMgr.LoadScriptWaypoints();
|
|
}
|
|
|
|
struct TSpellSummary
|
|
{
|
|
uint8 Targets; // set of enum SelectTarget
|
|
uint8 Effects; // set of enum SelectEffect
|
|
} *SpellSummary;
|
|
|
|
void ScriptMgr::FillSpellSummary()
|
|
{
|
|
SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()];
|
|
|
|
SpellEntry const* pTempSpell;
|
|
|
|
for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
|
|
{
|
|
SpellSummary[i].Effects = 0;
|
|
SpellSummary[i].Targets = 0;
|
|
|
|
pTempSpell = GetSpellStore()->LookupEntry(i);
|
|
//This spell doesn't exist
|
|
if (!pTempSpell)
|
|
continue;
|
|
|
|
for (uint32 j = 0; j < 3; ++j)
|
|
{
|
|
//Spell targets self
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1);
|
|
|
|
//Spell targets a single enemy
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
|
|
|
|
//Spell targets AoE at enemy
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
|
|
|
|
//Spell targets an enemy
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
|
|
|
|
//Spell targets a single friend(or self)
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
|
|
|
|
//Spell targets aoe friends
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
|
|
|
|
//Spell targets any friend(or self)
|
|
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET ||
|
|
pTempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER)
|
|
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
|
|
|
|
//Make sure that this spell includes a damage effect
|
|
if (pTempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
|
|
pTempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
|
|
pTempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
|
|
pTempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH)
|
|
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
|
|
|
|
//Make sure that this spell includes a healing effect (or an apply aura with a periodic heal)
|
|
if (pTempSpell->Effect[j] == SPELL_EFFECT_HEAL ||
|
|
pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
|
|
pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL ||
|
|
(pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && pTempSpell->EffectApplyAuraName[j] == 8))
|
|
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1);
|
|
|
|
//Make sure that this spell applies an aura
|
|
if (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA)
|
|
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & script_vector)
|
|
{
|
|
SpellScriptsBounds bounds = objmgr.GetSpellScriptsBounds(spell_id);
|
|
|
|
for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
|
|
{
|
|
SpellHandlerScript* tmpscript = ScriptRegistry<SpellHandlerScript>::GetScriptById(itr->second);
|
|
if (!tmpscript)
|
|
continue;
|
|
|
|
SpellScript* script = tmpscript->GetSpellScript();
|
|
|
|
if (!script)
|
|
{
|
|
sLog.outError("Spell script %s for spell %u returned a NULL SpellScript pointer!", tmpscript->ToString(), spell_id);
|
|
continue;
|
|
}
|
|
|
|
script_vector.push_back(script);
|
|
}
|
|
}
|
|
|
|
void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > & script_vector)
|
|
{
|
|
SpellScriptsBounds bounds = objmgr.GetSpellScriptsBounds(spell_id);
|
|
script_vector.reserve(std::distance(bounds.first, bounds.second));
|
|
|
|
for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
|
|
{
|
|
SpellHandlerScript* tmpscript = ScriptRegistry<SpellHandlerScript>::GetScriptById(itr->second);
|
|
if (!tmpscript)
|
|
continue;
|
|
|
|
SpellScript* script = tmpscript->GetSpellScript();
|
|
|
|
if (!script)
|
|
{
|
|
sLog.outError("Spell script %s for spell %u returned a NULL SpellScript pointer!", tmpscript->ToString(), spell_id);
|
|
continue;
|
|
}
|
|
|
|
script_vector.push_back(std::make_pair(script, itr));
|
|
}
|
|
}
|
|
|
|
void ScriptMgr::OnNetworkStart()
|
|
{
|
|
FOREACH_SCRIPT(ServerScript)->OnNetworkStart();
|
|
}
|
|
|
|
void ScriptMgr::OnNetworkStop()
|
|
{
|
|
FOREACH_SCRIPT(ServerScript)->OnNetworkStop();
|
|
}
|
|
|
|
void ScriptMgr::OnSocketOpen(WorldSocket* socket)
|
|
{
|
|
ASSERT(socket);
|
|
|
|
FOREACH_SCRIPT(ServerScript)->OnSocketOpen(socket);
|
|
}
|
|
|
|
void ScriptMgr::OnSocketClose(WorldSocket* socket, bool wasNew)
|
|
{
|
|
ASSERT(socket);
|
|
|
|
FOREACH_SCRIPT(ServerScript)->OnSocketClose(socket, wasNew);
|
|
}
|
|
|
|
void ScriptMgr::OnPacketReceive(WorldSocket* socket, WorldPacket& packet)
|
|
{
|
|
ASSERT(socket);
|
|
|
|
FOREACH_SCRIPT(ServerScript)->OnPacketReceive(socket, packet);
|
|
}
|
|
|
|
void ScriptMgr::OnPacketSend(WorldSocket* socket, WorldPacket& packet)
|
|
{
|
|
ASSERT(socket);
|
|
|
|
FOREACH_SCRIPT(ServerScript)->OnPacketSend(socket, packet);
|
|
}
|
|
|
|
void ScriptMgr::OnUnknownPacketReceive(WorldSocket* socket, WorldPacket& packet)
|
|
{
|
|
ASSERT(socket);
|
|
|
|
FOREACH_SCRIPT(ServerScript)->OnUnknownPacketReceive(socket, packet);
|
|
}
|
|
|
|
void ScriptMgr::OnOpenStateChange(bool open)
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnOpenStateChange(open);
|
|
}
|
|
|
|
void ScriptMgr::OnConfigLoad(bool reload)
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnConfigLoad(reload);
|
|
}
|
|
|
|
void ScriptMgr::OnMotdChange(std::string& newMotd)
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnMotdChange(newMotd);
|
|
}
|
|
|
|
void ScriptMgr::OnShutdown(ShutdownExitCode code, ShutdownMask mask)
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnShutdown(code, mask);
|
|
}
|
|
|
|
void ScriptMgr::OnShutdownCancel()
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnShutdownCancel();
|
|
}
|
|
|
|
void ScriptMgr::OnWorldUpdate(uint32 diff)
|
|
{
|
|
FOREACH_SCRIPT(WorldScript)->OnUpdate(NULL, diff);
|
|
}
|
|
|
|
void ScriptMgr::OnHonorCalculation(float& honor, uint8 level, uint32 count)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnHonorCalculation(honor, level, count);
|
|
}
|
|
|
|
void ScriptMgr::OnHonorCalculation(uint32& honor, uint8 level, uint32 count)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnHonorCalculation(honor, level, count);
|
|
}
|
|
|
|
void ScriptMgr::OnGetGrayLevel(uint8& grayLevel, uint8 playerLevel)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetGrayLevel(grayLevel, playerLevel);
|
|
}
|
|
|
|
void ScriptMgr::OnGetColorCode(XPColorChar& color, uint8 playerLevel, uint8 mobLevel)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetColorCode(color, playerLevel, mobLevel);
|
|
}
|
|
|
|
void ScriptMgr::OnGetZeroDifference(uint8& diff, uint8 playerLevel)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetZeroDifference(diff, playerLevel);
|
|
}
|
|
|
|
void ScriptMgr::OnGetBaseGain(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetBaseGain(gain, playerLevel, mobLevel, content);
|
|
}
|
|
|
|
void ScriptMgr::OnGetGain(uint32& gain, Player* player, Unit* unit)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(unit);
|
|
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetGain(gain, player, unit);
|
|
}
|
|
|
|
void ScriptMgr::OnGetGroupRate(float& rate, uint32 count, bool isRaid)
|
|
{
|
|
FOREACH_SCRIPT(FormulaScript)->OnGetGroupRate(rate, count, isRaid);
|
|
}
|
|
|
|
#define SCR_MAP_BGN(M,V,I,E,C,T) \
|
|
if (V->GetEntry()->T()) \
|
|
{ \
|
|
FOR_SCRIPTS(M, I, E) \
|
|
{ \
|
|
MapEntry const* C = I->second->GetEntry(); \
|
|
if (!C) \
|
|
continue; \
|
|
if (entry->MapID == V->GetId()) \
|
|
{
|
|
|
|
#define SCR_MAP_END \
|
|
break; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
void ScriptMgr::OnCreateMap(Map* map)
|
|
{
|
|
ASSERT(map);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnCreate(map);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnCreate((InstanceMap*)map);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnCreate((BattleGroundMap*)map);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnDestroyMap(Map* map)
|
|
{
|
|
ASSERT(map);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnDestroy(map);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnDestroy((InstanceMap*)map);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnDestroy((BattleGroundMap*)map);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnLoadGridMap(Map* map, uint32 gx, uint32 gy)
|
|
{
|
|
ASSERT(map);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnLoadGridMap(map, gx, gy);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnLoadGridMap((InstanceMap*)map, gx, gy);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnLoadGridMap((BattleGroundMap*)map, gx, gy);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnUnloadGridMap(Map* map, uint32 gx, uint32 gy)
|
|
{
|
|
ASSERT(map);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnUnloadGridMap(map, gx, gy);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnUnloadGridMap((InstanceMap*)map, gx, gy);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnUnloadGridMap((BattleGroundMap*)map, gx, gy);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnPlayerEnter(Map* map, Player* player)
|
|
{
|
|
ASSERT(map);
|
|
ASSERT(player);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnPlayerEnter(map, player);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnPlayerEnter((InstanceMap*)map, player);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnPlayerEnter((BattleGroundMap*)map, player);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnPlayerLeave(Map* map, Player* player)
|
|
{
|
|
ASSERT(map);
|
|
ASSERT(player);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnPlayerLeave(map, player);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnPlayerLeave((InstanceMap*)map, player);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnPlayerLeave((BattleGroundMap*)map, player);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
void ScriptMgr::OnMapUpdate(Map* map, uint32 diff)
|
|
{
|
|
ASSERT(map);
|
|
|
|
SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
|
|
itr->second->OnUpdate(map, diff);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
|
|
itr->second->OnUpdate((InstanceMap*)map, diff);
|
|
SCR_MAP_END;
|
|
|
|
SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleGround);
|
|
itr->second->OnUpdate((BattleGroundMap*)map, diff);
|
|
SCR_MAP_END;
|
|
}
|
|
|
|
#undef SCR_MAP_BGN
|
|
#undef SCR_MAP_END
|
|
|
|
InstanceData* ScriptMgr::CreateInstanceData(InstanceMap* map)
|
|
{
|
|
ASSERT(map);
|
|
|
|
GET_SCRIPT_RET(InstanceMapScript, map->GetScriptId(), tmpscript, NULL);
|
|
return tmpscript->OnGetInstanceData(map);
|
|
}
|
|
|
|
bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Item* target)
|
|
{
|
|
ASSERT(caster);
|
|
ASSERT(target);
|
|
|
|
GET_SCRIPT_RET(ItemScript, target->GetProto()->ScriptId, tmpscript, false);
|
|
return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestAccept(Player* player, Item* item, Quest const* quest)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(item);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(ItemScript, item->GetProto()->ScriptId, tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestAccept(player, item, quest);
|
|
}
|
|
|
|
bool ScriptMgr::OnItemUse(Player* player, Item* item, SpellCastTargets const& targets)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(item);
|
|
|
|
GET_SCRIPT_RET(ItemScript, item->GetProto()->ScriptId, tmpscript, false);
|
|
return tmpscript->OnUse(player, item, targets);
|
|
}
|
|
|
|
bool ScriptMgr::OnItemExpire(Player* player, ItemPrototype const* proto)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(proto);
|
|
|
|
GET_SCRIPT_RET(ItemScript, proto->ScriptId, tmpscript, false);
|
|
return tmpscript->OnExpire(player, proto);
|
|
}
|
|
|
|
bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Creature* target)
|
|
{
|
|
ASSERT(caster);
|
|
ASSERT(target);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, target->GetScriptId(), tmpscript, false);
|
|
return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipHello(Player* player, Creature* creature)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipHello(player, creature);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipSelect(player, creature, sender, action);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
ASSERT(code);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipSelectCode(player, creature, sender, action, code);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestAccept(player, creature, quest);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestSelect(Player* player, Creature* creature, Quest const* quest)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestSelect(player, creature, quest);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestComplete(Player* player, Creature* creature, Quest const* quest)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestComplete(player, creature, quest);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestReward(player, creature, quest, opt);
|
|
}
|
|
|
|
uint32 ScriptMgr::GetDialogStatus(Player* player, Creature* creature)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(creature);
|
|
|
|
// TODO: 100 is a funny magic number to have hanging around here...
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, 100);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnDialogStatus(player, creature);
|
|
}
|
|
|
|
CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature)
|
|
{
|
|
ASSERT(creature);
|
|
|
|
GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, NULL);
|
|
return tmpscript->OnGetAI();
|
|
}
|
|
|
|
void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff)
|
|
{
|
|
ASSERT(creature);
|
|
|
|
GET_SCRIPT(CreatureScript, creature->GetScriptId(), tmpscript);
|
|
tmpscript->OnUpdate(creature, diff);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipHello(Player* player, GameObject* go)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipHello(player, go);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipSelect(player, go, sender, action);
|
|
}
|
|
|
|
bool ScriptMgr::OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
ASSERT(code);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnGossipSelectCode(player, go, sender, action, code);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestAccept(Player* player, GameObject* go, Quest const* quest)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestAccept(player, go, quest);
|
|
}
|
|
|
|
bool ScriptMgr::OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
ASSERT(quest);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnQuestReward(player, go, quest, opt);
|
|
}
|
|
|
|
uint32 ScriptMgr::GetDialogStatus(Player* player, GameObject* go)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
|
|
// TODO: 100 is a funny magic number to have hanging around here...
|
|
GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, 100);
|
|
player->PlayerTalkClass->ClearMenus();
|
|
return tmpscript->OnDialogStatus(player, go);
|
|
}
|
|
|
|
void ScriptMgr::OnGameObjectDestroyed(Player* player, GameObject* go, uint32 eventId)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(go);
|
|
|
|
GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
|
|
tmpscript->OnDestroyed(player, go, eventId);
|
|
}
|
|
|
|
void ScriptMgr::OnGameObjectUpdate(GameObject* go, uint32 diff)
|
|
{
|
|
ASSERT(go);
|
|
|
|
GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
|
|
tmpscript->OnUpdate(go, diff);
|
|
}
|
|
|
|
bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, GameObject* target)
|
|
{
|
|
ASSERT(caster);
|
|
ASSERT(target);
|
|
|
|
GET_SCRIPT_RET(GameObjectScript, target->GetScriptId(), tmpscript, false);
|
|
return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
|
|
}
|
|
|
|
bool ScriptMgr::OnTrigger(Player* player, AreaTriggerEntry const* trigger)
|
|
{
|
|
ASSERT(player);
|
|
ASSERT(trigger);
|
|
|
|
GET_SCRIPT_RET(AreaTriggerScript, trigger->id, tmpscript, false);
|
|
return tmpscript->OnTrigger(player, trigger);
|
|
}
|
|
|
|
BattleGround* ScriptMgr::CreateBattleground(BattleGroundTypeId typeId)
|
|
{
|
|
// TODO: Implement script-side battlegrounds.
|
|
ASSERT(false);
|
|
return NULL;
|
|
}
|
|
|
|
OutdoorPvP* ScriptMgr::CreateOutdoorPvP(OutdoorPvPData const* data)
|
|
{
|
|
ASSERT(data);
|
|
|
|
GET_SCRIPT_RET(OutdoorPvPScript, data->ScriptId, tmpscript, NULL);
|
|
return tmpscript->OnGetOutdoorPvP();
|
|
}
|
|
|
|
std::vector<ChatCommand*> ScriptMgr::GetChatCommands()
|
|
{
|
|
std::vector<ChatCommand*> table;
|
|
|
|
FOR_SCRIPTS_RET(CommandScript, itr, end, table)
|
|
table.push_back(itr->second->OnGetCommands());
|
|
|
|
return table;
|
|
}
|
|
|
|
void ScriptMgr::OnWeatherChange(Weather* weather, WeatherState state, float grade)
|
|
{
|
|
ASSERT(weather);
|
|
|
|
GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript);
|
|
tmpscript->OnChange(weather, state, grade);
|
|
}
|
|
|
|
void ScriptMgr::OnWeatherUpdate(Weather* weather, uint32 diff)
|
|
{
|
|
ASSERT(weather);
|
|
|
|
GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript);
|
|
tmpscript->OnUpdate(weather, diff);
|
|
}
|
|
|
|
void ScriptMgr::OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry)
|
|
{
|
|
ASSERT(ah);
|
|
ASSERT(entry);
|
|
|
|
FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionAdd(ah, entry);
|
|
}
|
|
|
|
void ScriptMgr::OnRemoveAuction(AuctionHouseObject* ah, AuctionEntry* entry)
|
|
{
|
|
ASSERT(ah);
|
|
ASSERT(entry);
|
|
|
|
FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionRemove(ah, entry);
|
|
}
|
|
|
|
void ScriptMgr::OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry)
|
|
{
|
|
ASSERT(ah);
|
|
ASSERT(entry);
|
|
|
|
FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionSuccessful(ah, entry);
|
|
}
|
|
|
|
void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry)
|
|
{
|
|
ASSERT(ah);
|
|
ASSERT(entry);
|
|
|
|
FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry);
|
|
}
|
|
|
|
bool ScriptMgr::OnConditionCheck(Condition* condition, Player* player, Unit* targetOverride)
|
|
{
|
|
ASSERT(condition);
|
|
ASSERT(player);
|
|
|
|
GET_SCRIPT_RET(ConditionScript, condition->mScriptId, tmpscript, true);
|
|
return tmpscript->OnConditionCheck(condition, player, targetOverride);
|
|
}
|
|
|
|
void ScriptMgr::OnInstall(Vehicle* veh)
|
|
{
|
|
ASSERT(veh);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnInstall(veh);
|
|
}
|
|
|
|
void ScriptMgr::OnUninstall(Vehicle* veh)
|
|
{
|
|
ASSERT(veh);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnUninstall(veh);
|
|
}
|
|
|
|
void ScriptMgr::OnDie(Vehicle* veh)
|
|
{
|
|
ASSERT(veh);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnDie(veh);
|
|
}
|
|
|
|
void ScriptMgr::OnReset(Vehicle* veh)
|
|
{
|
|
ASSERT(veh);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnReset(veh);
|
|
}
|
|
|
|
void ScriptMgr::OnInstallAccessory(Vehicle* veh, Creature* accessory)
|
|
{
|
|
ASSERT(veh);
|
|
ASSERT(accessory);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnInstallAccessory(veh, accessory);
|
|
}
|
|
|
|
void ScriptMgr::OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId)
|
|
{
|
|
ASSERT(veh);
|
|
ASSERT(passenger);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnAddPassenger(veh, passenger, seatId);
|
|
}
|
|
|
|
void ScriptMgr::OnRemovePassenger(Vehicle* veh, Unit* passenger)
|
|
{
|
|
ASSERT(veh);
|
|
ASSERT(passenger);
|
|
|
|
FOREACH_SCRIPT(VehicleScript)->OnRemovePassenger(veh, passenger);
|
|
}
|
|
|
|
void ScriptMgr::OnDynamicObjectUpdate(DynamicObject* dynobj, uint32 diff)
|
|
{
|
|
ASSERT(dynobj);
|
|
|
|
FOR_SCRIPTS(DynamicObjectScript, itr, end)
|
|
itr->second->OnUpdate(dynobj, diff);
|
|
}
|
|
|
|
void ScriptMgr::OnAddPassenger(Transport* transport, Player* player)
|
|
{
|
|
ASSERT(transport);
|
|
ASSERT(player);
|
|
|
|
GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
|
|
tmpscript->OnAddPassenger(transport, player);
|
|
}
|
|
|
|
void ScriptMgr::OnAddCreaturePassenger(Transport* transport, Creature* creature)
|
|
{
|
|
ASSERT(transport);
|
|
ASSERT(creature);
|
|
|
|
GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
|
|
tmpscript->OnAddCreaturePassenger(transport, creature);
|
|
}
|
|
|
|
void ScriptMgr::OnRemovePassenger(Transport* transport, Player* player)
|
|
{
|
|
ASSERT(transport);
|
|
ASSERT(player);
|
|
|
|
GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
|
|
tmpscript->OnRemovePassenger(transport, player);
|
|
}
|
|
|
|
void ScriptMgr::OnTransportUpdate(Transport* transport, uint32 diff)
|
|
{
|
|
ASSERT(transport);
|
|
|
|
GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
|
|
tmpscript->OnUpdate(transport, diff);
|
|
}
|
|
|
|
void SpellHandlerScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<SpellHandlerScript>::AddScript(this);
|
|
}
|
|
|
|
void AuraHandlerScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<AuraHandlerScript>::AddScript(this);
|
|
}
|
|
|
|
void ServerScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<ServerScript>::AddScript(this);
|
|
}
|
|
|
|
void WorldScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<WorldScript>::AddScript(this);
|
|
}
|
|
|
|
void FormulaScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<FormulaScript>::AddScript(this);
|
|
}
|
|
|
|
void WorldMapScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<WorldMapScript>::AddScript(this);
|
|
}
|
|
|
|
void InstanceMapScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<InstanceMapScript>::AddScript(this);
|
|
}
|
|
|
|
void BattlegroundMapScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<BattlegroundMapScript>::AddScript(this);
|
|
}
|
|
|
|
void AreaTriggerScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<AreaTriggerScript>::AddScript(this);
|
|
}
|
|
|
|
void ItemScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<ItemScript>::AddScript(this);
|
|
}
|
|
|
|
void CreatureScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<CreatureScript>::AddScript(this);
|
|
}
|
|
|
|
void GameObjectScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<GameObjectScript>::AddScript(this);
|
|
}
|
|
|
|
void BattlegroundScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<BattlegroundScript>::AddScript(this);
|
|
}
|
|
|
|
void OutdoorPvPScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<OutdoorPvPScript>::AddScript(this);
|
|
}
|
|
|
|
void CommandScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<CommandScript>::AddScript(this);
|
|
}
|
|
|
|
void WeatherScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<WeatherScript>::AddScript(this);
|
|
}
|
|
|
|
void AuctionHouseScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<AuctionHouseScript>::AddScript(this);
|
|
}
|
|
|
|
void ConditionScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<ConditionScript>::AddScript(this);
|
|
}
|
|
|
|
void VehicleScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<VehicleScript>::AddScript(this);
|
|
}
|
|
|
|
void DynamicObjectScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<DynamicObjectScript>::AddScript(this);
|
|
}
|
|
|
|
void TransportScript::RegisterSelf()
|
|
{
|
|
ScriptMgr::ScriptRegistry<TransportScript>::AddScript(this);
|
|
}
|
|
|
|
template<class TScript>
|
|
void ScriptMgr::ScriptRegistry<TScript>::AddScript(TScript* const script)
|
|
{
|
|
ASSERT(script);
|
|
|
|
// See if the script is using the same memory as another script. If this happens, it means that
|
|
// someone forgot to allocate new memory for a script.
|
|
for (ScriptMap::iterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
|
{
|
|
if (it->second == script)
|
|
{
|
|
sLog.outError("Script '%s' forgot to allocate memory, so this script and/or the script before that can't work.",
|
|
script->ToString());
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Get an ID for the script. An ID only exists if it's a script that is assigned in the database
|
|
// through a script name (or similar).
|
|
uint32 id = GetScriptId(script->ToString());
|
|
if (id)
|
|
{
|
|
// Try to find an existing script.
|
|
bool existing = false;
|
|
for (ScriptMap::iterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
|
{
|
|
// If the script names match...
|
|
if (it->second->GetName() == script->GetName())
|
|
{
|
|
// ... It exists.
|
|
existing = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If the script isn't assigned -> assign it!
|
|
if (!existing)
|
|
{
|
|
ScriptPointerList[id] = script;
|
|
sScriptMgr.IncrementScriptCount();
|
|
}
|
|
else
|
|
{
|
|
// If the script is already assigned -> delete it!
|
|
sLog.outError("Script '%s' already assigned with the same script name, so the script can't work.",
|
|
script->ToString());
|
|
|
|
delete script;
|
|
}
|
|
}
|
|
else if (script->IsDatabaseBound())
|
|
{
|
|
// The script uses a script name from database, but isn't assigned to anything.
|
|
if (script->GetName().find("example") == std::string::npos)
|
|
sLog.outErrorDb("Script named '%s' does not have a script name assigned in database.",
|
|
script->ToString());
|
|
|
|
delete script;
|
|
}
|
|
else
|
|
{
|
|
// We're dealing with a code-only script; just add it.
|
|
ScriptPointerList[_scriptIdCounter++] = script;
|
|
sScriptMgr.IncrementScriptCount();
|
|
}
|
|
}
|
|
|
|
// Instantiate static members of ScriptMgr::ScriptRegistry.
|
|
template<class TScript> std::map<uint32, TScript*> ScriptMgr::ScriptRegistry<TScript>::ScriptPointerList;
|
|
template<class TScript> uint32 ScriptMgr::ScriptRegistry<TScript>::_scriptIdCounter;
|
|
|
|
// Specialize for each script type class like so:
|
|
template class ScriptMgr::ScriptRegistry<SpellHandlerScript>;
|
|
template class ScriptMgr::ScriptRegistry<AuraHandlerScript>;
|
|
template class ScriptMgr::ScriptRegistry<ServerScript>;
|
|
template class ScriptMgr::ScriptRegistry<WorldScript>;
|
|
template class ScriptMgr::ScriptRegistry<FormulaScript>;
|
|
template class ScriptMgr::ScriptRegistry<WorldMapScript>;
|
|
template class ScriptMgr::ScriptRegistry<InstanceMapScript>;
|
|
template class ScriptMgr::ScriptRegistry<BattlegroundMapScript>;
|
|
template class ScriptMgr::ScriptRegistry<ItemScript>;
|
|
template class ScriptMgr::ScriptRegistry<CreatureScript>;
|
|
template class ScriptMgr::ScriptRegistry<GameObjectScript>;
|
|
template class ScriptMgr::ScriptRegistry<AreaTriggerScript>;
|
|
template class ScriptMgr::ScriptRegistry<BattlegroundScript>;
|
|
template class ScriptMgr::ScriptRegistry<OutdoorPvPScript>;
|
|
template class ScriptMgr::ScriptRegistry<CommandScript>;
|
|
template class ScriptMgr::ScriptRegistry<WeatherScript>;
|
|
template class ScriptMgr::ScriptRegistry<AuctionHouseScript>;
|
|
template class ScriptMgr::ScriptRegistry<ConditionScript>;
|
|
template class ScriptMgr::ScriptRegistry<VehicleScript>;
|
|
template class ScriptMgr::ScriptRegistry<DynamicObjectScript>;
|
|
template class ScriptMgr::ScriptRegistry<TransportScript>;
|
|
|
|
// Undefine utility macros.
|
|
#undef GET_SCRIPT_RET
|
|
#undef GET_SCRIPT
|
|
#undef FOREACH_SCRIPT
|
|
#undef FOR_SCRIPTS_RET
|
|
#undef FOR_SCRIPTS
|
|
#undef SCR_REG_LST
|
|
#undef SCR_REG_MAP
|