diff options
Diffstat (limited to 'src/server/game/Scripting')
| -rw-r--r-- | src/server/game/Scripting/ScriptMgr.cpp | 1282 | ||||
| -rw-r--r-- | src/server/game/Scripting/ScriptMgr.h | 1006 | ||||
| -rw-r--r-- | src/server/game/Scripting/ScriptSystem.h | 2 |
3 files changed, 1853 insertions, 437 deletions
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 5f6cce4917d..8e660f7116e 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -11,69 +11,34 @@ #include "ScriptLoader.h" #include "ScriptSystem.h" -int num_sc_scripts; -Script *m_scripts[MAX_SCRIPTS]; - -void FillSpellSummary(); -void LoadOverridenSQLData(); - -void ScriptMgr::LoadDatabase() -{ - pSystemMgr.LoadVersion(); - pSystemMgr.LoadScriptTexts(); - pSystemMgr.LoadScriptTextsCustom(); - pSystemMgr.LoadScriptWaypoints(); -} - -struct TSpellSummary { - uint8 Targets; // set of enum SelectTarget - uint8 Effects; // set of enum SelectEffect -}extern *SpellSummary; - -ScriptMgr::ScriptMgr() -{ - -} -ScriptMgr::~ScriptMgr() -{ - -} - -void ScriptMgr::ScriptsInit() -{ - //Trinity Script startup - /*sLog.outString(" _____ _ _ _ ____ _ _"); - sLog.outString("|_ _| __(_)_ __ (_) |_ _ _/ ___| ___ _ __(_)_ __ | |_ "); - sLog.outString(" | || '__| | '_ \\| | __| | | \\___ \\ / __| \'__| | \'_ \\| __|"); - sLog.outString(" | || | | | | | | | |_| |_| |___) | (__| | | | |_) | |_ "); - sLog.outString(" |_||_| |_|_| |_|_|\\__|\\__, |____/ \\___|_| |_| .__/ \\__|"); - sLog.outString(" |___/ |_| "); - sLog.outString(""); - sLog.outString("");*/ - - //Load database (must be called after SD2Config.SetSource). - LoadDatabase(); - - sLog.outString("Loading C++ scripts"); - barGoLink bar(1); - bar.step(); - sLog.outString(""); - - for (uint16 i =0; i<MAX_SCRIPTS; ++i) - m_scripts[i]=NULL; - - FillSpellSummary(); - - AddScripts(); - - sLog.outString(">> Loaded %i C++ Scripts.", num_sc_scripts); - - sLog.outString(">> Load Overriden SQL Data."); - LoadOverridenSQLData(); -} - -//********************************* -//*** Functions used globally *** +// 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) { @@ -89,7 +54,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) return; } - const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry); + const StringTextData* pData = sScriptSystemMgr.GetTextData(iTextEntry); if (!pData) { @@ -102,9 +67,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) 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); } @@ -117,7 +80,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) sLog.outError("TSCR: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId()); } - switch(pData->uiType) + switch (pData->uiType) { case CHAT_TYPE_SAY: pSource->MonsterSay(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); @@ -132,437 +95,1122 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) 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); - } + { + 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); - } + { + 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; } } -void Script::RegisterSelf() +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() { - // try to find scripts which try to use another script's allocated memory - // that means didn't allocate memory for script - for (uint16 i = 0; i < MAX_SCRIPTS; ++i) + 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) { - // somebody forgot to allocate memory for a script by a method like this: newscript = new Script - if (m_scripts[i] == this) + 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) { - sLog.outError("ScriptName: '%s' - Forgot to allocate memory, so this script and/or the script before that can't work.", Name.c_str()); - // don't register it - // and don't delete it because its memory is used for another script - return; + //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); } } +} - int id = GetScriptId(Name.c_str()); - if (id) +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) { - // try to find the script in assigned scripts - bool IsExist = false; - for (uint16 i = 0; i < MAX_SCRIPTS; ++i) - { - if (m_scripts[i]) - { - // if the assigned script's name and the new script's name is the same - if (m_scripts[i]->Name == Name) - { - IsExist = true; - break; - } - } - } + SpellHandlerScript* tmpscript = ScriptRegistry<SpellHandlerScript>::GetScriptById(itr->second); + if (!tmpscript) + continue; - // if the script doesn't assigned -> assign it! - if (!IsExist) + SpellScript* script = tmpscript->GetSpellScript(); + + if (!script) { - m_scripts[id] = this; - ++num_sc_scripts; + sLog.outError("Spell script %s for spell %u returned a NULL SpellScript pointer!", tmpscript->ToString(), spell_id); + continue; } - // if the script is already assigned -> delete it! - else + + 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) { - // TODO: write a better error message than this one :) - sLog.outError("ScriptName: '%s' already assigned with the same ScriptName, so the script can't work.", Name.c_str()); - delete this; + 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)); } - else - { - if (Name.find("example") == std::string::npos) - sLog.outErrorDb("TrinityScript: RegisterSelf, but script named %s does not have ScriptName assigned in database.",(this)->Name.c_str()); - delete this; +} + +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::OnLogin(Player *pPlayer) +void ScriptMgr::OnDestroyMap(Map* map) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnLogin) return; - tmpscript->pOnLogin(pPlayer); + 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::OnLogout(Player *pPlayer) +void ScriptMgr::OnLoadGridMap(Map* map, uint32 gx, uint32 gy) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnLogout) return; - tmpscript->pOnLogout(pPlayer); + 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::OnPVPKill(Player *killer, Player *killed) +void ScriptMgr::OnUnloadGridMap(Map* map, uint32 gx, uint32 gy) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnPVPKill) return; - tmpscript->pOnPVPKill(killer, killed); + 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; } -bool ScriptMgr::OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell) +void ScriptMgr::OnPlayerEnter(Map* map, Player* player) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnSpellCast) return true; - return tmpscript->pOnSpellCast(pUnitTarget,pItemTarget,pGoTarget,i,spell); + 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; } -uint32 ScriptMgr::OnGetXP(Player *pPlayer, uint32 amount) +void ScriptMgr::OnPlayerLeave(Map* map, Player* player) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGetXP) return amount; - return tmpscript->pOnGetXP(pPlayer,amount); + 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; } -uint32 ScriptMgr::OnGetMoney(Player *pPlayer, int32 amount) +void ScriptMgr::OnMapUpdate(Map* map, uint32 diff) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGetMoney) return amount; - return tmpscript->pOnGetMoney(pPlayer,amount); + 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; } -bool ScriptMgr::OnPlayerChat(Player *pPlayer, const char *text) +#undef SCR_MAP_BGN +#undef SCR_MAP_END + +InstanceData* ScriptMgr::CreateInstanceData(InstanceMap* map) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnPlayerChat) return true; - return tmpscript->pOnPlayerChat(pPlayer,text); + ASSERT(map); + + GET_SCRIPT_RET(InstanceMapScript, map->GetScriptId(), tmpscript, NULL); + return tmpscript->OnGetInstanceData(map); } -void ScriptMgr::OnServerStartup() +bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Item* target) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnServerStartup) return; - tmpscript->pOnServerStartup(); + ASSERT(caster); + ASSERT(target); + + GET_SCRIPT_RET(ItemScript, target->GetProto()->ScriptId, tmpscript, false); + return tmpscript->OnDummyEffect(caster, spellId, effIndex, target); } -void ScriptMgr::OnServerShutdown() +bool ScriptMgr::OnQuestAccept(Player* player, Item* item, Quest const* quest) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnServerShutdown) return; - tmpscript->pOnServerShutdown(); + ASSERT(player); + ASSERT(item); + ASSERT(quest); + + GET_SCRIPT_RET(ItemScript, item->GetProto()->ScriptId, tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestAccept(player, item, quest); } -void ScriptMgr::OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea) +bool ScriptMgr::OnItemUse(Player* player, Item* item, SpellCastTargets const& targets) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnAreaChange) return; - tmpscript->pOnAreaChange(pPlayer, pArea); + ASSERT(player); + ASSERT(item); + + GET_SCRIPT_RET(ItemScript, item->GetProto()->ScriptId, tmpscript, false); + return tmpscript->OnUse(player, item, targets); } -bool ScriptMgr::OnItemClick (Player *pPlayer, Item *pItem) +bool ScriptMgr::OnItemExpire(Player* player, ItemPrototype const* proto) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnItemClick) return true; - return tmpscript->pOnItemClick(pPlayer,pItem); + ASSERT(player); + ASSERT(proto); + + GET_SCRIPT_RET(ItemScript, proto->ScriptId, tmpscript, false); + return tmpscript->OnExpire(player, proto); } -bool ScriptMgr::OnItemOpen (Player *pPlayer, Item *pItem) +bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Creature* target) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnItemOpen) return true; - return tmpscript->pOnItemOpen(pPlayer,pItem); + ASSERT(caster); + ASSERT(target); + + GET_SCRIPT_RET(CreatureScript, target->GetScriptId(), tmpscript, false); + return tmpscript->OnDummyEffect(caster, spellId, effIndex, target); } -bool ScriptMgr::OnGoClick (Player *pPlayer, GameObject *pGameObject) +bool ScriptMgr::OnGossipHello(Player* player, Creature* creature) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGoClick) return true; - return tmpscript->pOnGoClick(pPlayer,pGameObject); + ASSERT(player); + ASSERT(creature); + + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnGossipHello(player, creature); } -void ScriptMgr::OnCreatureKill (Player *pPlayer, Creature *pCreature) +bool ScriptMgr::OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) { - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnCreatureKill) return; - tmpscript->pOnCreatureKill(pPlayer,pCreature); + ASSERT(player); + ASSERT(creature); + + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnGossipSelect(player, creature, sender, action); } -char const* ScriptMgr::ScriptsVersion() +bool ScriptMgr::OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code) { - return "Integrated Trinity Scripts"; + 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::GossipHello (Player * pPlayer, Creature* pCreature) +bool ScriptMgr::OnQuestAccept(Player* player, Creature* creature, Quest const* quest) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipHello) return false; + ASSERT(player); + ASSERT(creature); + ASSERT(quest); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipHello(pPlayer, pCreature); + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestAccept(player, creature, quest); } -bool ScriptMgr::GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +bool ScriptMgr::OnQuestSelect(Player* player, Creature* creature, Quest const* quest) { - sLog.outDebug("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); + ASSERT(player); + ASSERT(creature); + ASSERT(quest); + + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestSelect(player, creature, quest); +} - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipSelect) return false; +bool ScriptMgr::OnQuestComplete(Player* player, Creature* creature, Quest const* quest) +{ + ASSERT(player); + ASSERT(creature); + ASSERT(quest); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipSelect(pPlayer, pCreature, uiSender, uiAction); + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestComplete(player, creature, quest); } -bool ScriptMgr::GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) +bool ScriptMgr::OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt) { - sLog.outDebug("TSCR: Gossip selection with code, sender: %d, action: %d", uiSender, uiAction); + ASSERT(player); + ASSERT(creature); + ASSERT(quest); - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipSelectWithCode) return false; + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestReward(player, creature, quest, opt); +} - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipSelectWithCode(pPlayer, pCreature, uiSender, uiAction, sCode); +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); } -bool ScriptMgr::GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction) +CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature) { - if (!pGO) - return false; - sLog.outDebug("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); + ASSERT(creature); - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOSelect) return false; + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, NULL); + return tmpscript->OnGetAI(); +} - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOSelect(pPlayer, pGO, uiSender, uiAction); +void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff) +{ + ASSERT(creature); + + GET_SCRIPT(CreatureScript, creature->GetScriptId(), tmpscript); + tmpscript->OnUpdate(creature, diff); } -bool ScriptMgr::GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode) +bool ScriptMgr::OnGossipHello(Player* player, GameObject* go) { - if (!pGO) - return false; - sLog.outDebug("TSCR: Gossip selection, sender: %d, action: %d",uiSender, uiAction); + ASSERT(player); + ASSERT(go); - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOSelectWithCode) return false; + GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnGossipHello(player, go); +} - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOSelectWithCode(pPlayer, pGO, uiSender ,uiAction, sCode); +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::QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +bool ScriptMgr::OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestAccept) return false; + ASSERT(player); + ASSERT(go); + ASSERT(code); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestAccept(pPlayer, pCreature, pQuest); + GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnGossipSelectCode(player, go, sender, action, code); } -bool ScriptMgr::QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +bool ScriptMgr::OnQuestAccept(Player* player, GameObject* go, Quest const* quest) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestSelect) return false; + ASSERT(player); + ASSERT(go); + ASSERT(quest); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestSelect(pPlayer, pCreature, pQuest); + GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestAccept(player, go, quest); } -bool ScriptMgr::QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +bool ScriptMgr::OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestComplete) return false; + ASSERT(player); + ASSERT(go); + ASSERT(quest); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestComplete(pPlayer, pCreature, pQuest); + GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false); + player->PlayerTalkClass->ClearMenus(); + return tmpscript->OnQuestReward(player, go, quest, opt); } -bool ScriptMgr::ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt) +uint32 ScriptMgr::GetDialogStatus(Player* player, GameObject* go) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pChooseReward) return false; + ASSERT(player); + ASSERT(go); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pChooseReward(pPlayer, pCreature, pQuest, opt); + // 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); } -uint32 ScriptMgr::NPCDialogStatus(Player* pPlayer, Creature* pCreature) +void ScriptMgr::OnGameObjectDestroyed(Player* player, GameObject* go, uint32 eventId) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pNPCDialogStatus) return 100; + ASSERT(player); + ASSERT(go); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pNPCDialogStatus(pPlayer, pCreature); + GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript); + tmpscript->OnDestroyed(player, go, eventId); } -uint32 ScriptMgr::GODialogStatus(Player* pPlayer, GameObject* pGO) +void ScriptMgr::OnGameObjectUpdate(GameObject* go, uint32 diff) { - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGODialogStatus) return 100; + ASSERT(go); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGODialogStatus(pPlayer, pGO); + GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript); + tmpscript->OnUpdate(go, diff); } -bool ScriptMgr::ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest) +bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, GameObject* target) { - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemHello) return false; + ASSERT(caster); + ASSERT(target); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pItemHello(pPlayer, pItem, pQuest); + GET_SCRIPT_RET(GameObjectScript, target->GetScriptId(), tmpscript, false); + return tmpscript->OnDummyEffect(caster, spellId, effIndex, target); } -bool ScriptMgr::ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest) +bool ScriptMgr::OnTrigger(Player* player, AreaTriggerEntry const* trigger) { - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemQuestAccept) return false; + ASSERT(player); + ASSERT(trigger); + + GET_SCRIPT_RET(AreaTriggerScript, trigger->id, tmpscript, false); + return tmpscript->OnTrigger(player, trigger); +} - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pItemQuestAccept(pPlayer, pItem, pQuest); +BattleGround* ScriptMgr::CreateBattleground(BattleGroundTypeId typeId) +{ + // TODO: Implement script-side battlegrounds. + ASSERT(false); + return NULL; } -bool ScriptMgr::GOHello(Player* pPlayer, GameObject* pGO) +OutdoorPvP* ScriptMgr::CreateOutdoorPvP(OutdoorPvPData const* data) { - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOHello) return false; + ASSERT(data); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOHello(pPlayer, pGO); + GET_SCRIPT_RET(OutdoorPvPScript, data->ScriptId, tmpscript, NULL); + return tmpscript->OnGetOutdoorPvP(); } -bool ScriptMgr::GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest) +std::vector<ChatCommand*> ScriptMgr::GetChatCommands() { - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOQuestAccept) return false; + std::vector<ChatCommand*> table; + + FOR_SCRIPTS_RET(CommandScript, itr, end, table) + table.push_back(itr->second->OnGetCommands()); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOQuestAccept(pPlayer, pGO, pQuest); + return table; } -bool ScriptMgr::GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt) +void ScriptMgr::OnWeatherChange(Weather* weather, WeatherState state, float grade) { - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOChooseReward) return false; + ASSERT(weather); - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOChooseReward(pPlayer, pGO, pQuest, opt); + GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript); + tmpscript->OnChange(weather, state, grade); } -void ScriptMgr::GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent) +void ScriptMgr::OnWeatherUpdate(Weather* weather, uint32 diff) { - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript) return; - tmpscript->pGODestroyed(pPlayer, pGO, destroyedEvent); + ASSERT(weather); + + GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript); + tmpscript->OnUpdate(weather, diff); } -bool ScriptMgr::AreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry) +void ScriptMgr::OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry) { - Script *tmpscript = m_scripts[GetAreaTriggerScriptId(atEntry->id)]; - if (!tmpscript || !tmpscript->pAreaTrigger) return false; + ASSERT(ah); + ASSERT(entry); - return tmpscript->pAreaTrigger(pPlayer, atEntry); + FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionAdd(ah, entry); } -CreatureAI* ScriptMgr::GetAI(Creature* pCreature) +void ScriptMgr::OnRemoveAuction(AuctionHouseObject* ah, AuctionEntry* entry) { - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->GetAI) return NULL; + ASSERT(ah); + ASSERT(entry); - return tmpscript->GetAI(pCreature); + FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionRemove(ah, entry); } -bool ScriptMgr::ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) +void ScriptMgr::OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry) { - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemUse) return false; + ASSERT(ah); + ASSERT(entry); - return tmpscript->pItemUse(pPlayer, pItem, targets); + FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionSuccessful(ah, entry); } -bool ScriptMgr::ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto) +void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) { - Script *tmpscript = m_scripts[pItemProto->ScriptId]; - if (!tmpscript || !tmpscript->pItemExpire) return true; + ASSERT(ah); + ASSERT(entry); - return tmpscript->pItemExpire(pPlayer, pItemProto); + FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry); } -bool ScriptMgr::EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget) +bool ScriptMgr::OnConditionCheck(Condition* condition, Player* player, Unit* targetOverride) { - Script *tmpscript = m_scripts[crTarget->GetScriptId()]; + ASSERT(condition); + ASSERT(player); + + GET_SCRIPT_RET(ConditionScript, condition->mScriptId, tmpscript, true); + return tmpscript->OnConditionCheck(condition, player, targetOverride); +} - if (!tmpscript || !tmpscript->pEffectDummyCreature) return false; +void ScriptMgr::OnInstall(Vehicle* veh) +{ + ASSERT(veh); - return tmpscript->pEffectDummyCreature(caster, spellId, effIndex, crTarget); + FOREACH_SCRIPT(VehicleScript)->OnInstall(veh); } -bool ScriptMgr::EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget) +void ScriptMgr::OnUninstall(Vehicle* veh) { - Script *tmpscript = m_scripts[gameObjTarget->GetGOInfo()->ScriptId]; + ASSERT(veh); - if (!tmpscript || !tmpscript->pEffectDummyGameObj) return false; + FOREACH_SCRIPT(VehicleScript)->OnUninstall(veh); +} - return tmpscript->pEffectDummyGameObj(caster, spellId, effIndex, gameObjTarget); +void ScriptMgr::OnDie(Vehicle* veh) +{ + ASSERT(veh); + + FOREACH_SCRIPT(VehicleScript)->OnDie(veh); } -bool ScriptMgr::EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget) +void ScriptMgr::OnReset(Vehicle* veh) { - Script *tmpscript = m_scripts[itemTarget->GetProto()->ScriptId]; + ASSERT(veh); + + FOREACH_SCRIPT(VehicleScript)->OnReset(veh); +} - if (!tmpscript || !tmpscript->pEffectDummyItem) return false; +void ScriptMgr::OnInstallAccessory(Vehicle* veh, Creature* accessory) +{ + ASSERT(veh); + ASSERT(accessory); - return tmpscript->pEffectDummyItem(caster, spellId, effIndex, itemTarget); + FOREACH_SCRIPT(VehicleScript)->OnInstallAccessory(veh, accessory); } -InstanceData* ScriptMgr::CreateInstanceData(Map *map) +void ScriptMgr::OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId) { - if (!map->IsDungeon()) return NULL; + ASSERT(veh); + ASSERT(passenger); - Script *tmpscript = m_scripts[((InstanceMap*)map)->GetScriptId()]; - if (!tmpscript || !tmpscript->GetInstanceData) return NULL; + FOREACH_SCRIPT(VehicleScript)->OnAddPassenger(veh, passenger, seatId); +} - return tmpscript->GetInstanceData(map); +void ScriptMgr::OnRemovePassenger(Vehicle* veh, Unit* passenger) +{ + ASSERT(veh); + ASSERT(passenger); + + FOREACH_SCRIPT(VehicleScript)->OnRemovePassenger(veh, passenger); } -void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & script_vector) +void ScriptMgr::OnDynamicObjectUpdate(DynamicObject* dynobj, uint32 diff) { - SpellScriptsBounds bounds = objmgr.GetSpellScriptsBounds(spell_id); - for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr) - { - Script *tmpscript = m_scripts[itr->second]; - if (!tmpscript || !tmpscript->GetSpellScript) continue; - script_vector.push_back(tmpscript->GetSpellScript()); - } + ASSERT(dynobj); + + FOR_SCRIPTS(DynamicObjectScript, itr, end) + itr->second->OnUpdate(dynobj, diff); } -void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > & script_vector) +void ScriptMgr::OnAddPassenger(Transport* transport, Player* player) { - 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) + 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) { - Script *tmpscript = m_scripts[itr->second]; - if (!tmpscript || !tmpscript->GetSpellScript) continue; - script_vector.push_back(std::make_pair(tmpscript->GetSpellScript(), itr)); + 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 diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 4ce6b403cea..64d8e92abea 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -13,6 +13,15 @@ #include "DBCStructure.h" #include "Config.h" #include "ObjectMgr.h" +#include "BattleGround.h" +#include "OutdoorPvPMgr.h" +#include "SharedDefines.h" +#include "Chat.h" +#include "Weather.h" +#include "AuctionHouseMgr.h" +#include "ConditionMgr.h" +#include "Vehicle.h" +#include "Transport.h" class Player; class Creature; @@ -28,134 +37,893 @@ class Unit; class WorldObject; struct ItemPrototype; class Spell; +class ScriptMgr; +class WorldSocket; -#define MAX_SCRIPTS 5000 //72 bytes each (approx 351kb) #define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid) #define DEFAULT_TEXT "<Trinity Script Text Entry Missing!>" -struct Script -{ - Script() : - pOnLogin(NULL), pOnLogout(NULL), pOnPVPKill(NULL), pOnSpellCast(NULL), pOnGetXP(NULL), - pOnGetMoney(NULL), pOnPlayerChat(NULL), pOnServerStartup(NULL), pOnServerShutdown(NULL), - pOnAreaChange(NULL), pOnItemClick(NULL), pOnItemOpen(NULL), pOnGoClick(NULL), pOnCreatureKill(NULL), - pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), - pGOSelect(NULL), pGOSelectWithCode(NULL), - pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), - pChooseReward(NULL), pGODestroyed(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), - pGOQuestAccept(NULL), pGOChooseReward(NULL),pItemUse(NULL), pItemExpire(NULL), - pEffectDummyCreature(NULL), pEffectDummyGameObj(NULL), pEffectDummyItem(NULL), - GetAI(NULL), GetInstanceData(NULL), GetSpellScript(NULL) - {} - - std::string Name; - - //Methods to be scripted - void (*pOnLogin)(Player*); - void (*pOnLogout)(Player*); - void (*pOnPVPKill)(Player*, Player*); - bool (*pOnSpellCast)(Unit*, Item*, GameObject*, uint32, SpellEntry const*); - uint32 (*pOnGetXP)(Player*, uint32); - int32 (*pOnGetMoney)(Player*, int32); - bool (*pOnPlayerChat)(Player*, const char*); - void (*pOnServerStartup)(); - void (*pOnServerShutdown)(); - void (*pOnAreaChange)(Player*, AreaTableEntry const*); - bool (*pOnItemClick)(Player*, Item*); - bool (*pOnItemOpen)(Player*, Item*); - bool (*pOnGoClick)(Player*, GameObject*); - void (*pOnCreatureKill)(Player*, Creature*); - bool (*pGossipHello)(Player*, Creature*); - bool (*pQuestAccept)(Player*, Creature*, Quest const*); - bool (*pGossipSelect)(Player*, Creature*, uint32 , uint32); - bool (*pGossipSelectWithCode)(Player*, Creature*, uint32 , uint32 , const char*); - bool (*pGOSelect)(Player*, GameObject*, uint32 , uint32); - bool (*pGOSelectWithCode)(Player*, GameObject*, uint32 , uint32 , const char*); - bool (*pQuestSelect)(Player*, Creature*, Quest const*); - bool (*pQuestComplete)(Player*, Creature*, Quest const*); - uint32 (*pNPCDialogStatus)(Player*, Creature*); - uint32 (*pGODialogStatus)(Player*, GameObject * _GO); - bool (*pChooseReward)(Player*, Creature*, Quest const*, uint32); - bool (*pItemHello)(Player*, Item*, Quest const*); - bool (*pGOHello)(Player*, GameObject*); - bool (*pAreaTrigger)(Player*, AreaTriggerEntry const*); - bool (*pItemQuestAccept)(Player*, Item *, Quest const*); - bool (*pGOQuestAccept)(Player*, GameObject*, Quest const*); - bool (*pGOChooseReward)(Player*, GameObject*, Quest const*, uint32); - void (*pGODestroyed)(Player*, GameObject*, uint32); - bool (*pItemUse)(Player*, Item*, SpellCastTargets const&); - bool (*pItemExpire)(Player*, ItemPrototype const *); - bool (*pEffectDummyCreature)(Unit*, uint32, uint32, Creature*); - bool (*pEffectDummyGameObj)(Unit*, uint32, uint32, GameObject*); - bool (*pEffectDummyItem)(Unit*, uint32, uint32, Item*); - - CreatureAI* (*GetAI)(Creature*); - InstanceData* (*GetInstanceData)(Map*); - - SpellScript*(*GetSpellScript)(); - //AuraScript*(*GetAuraScript)(); - - void RegisterSelf(); +// Generic scripting text function. +void DoScriptText(int32 textEntry, WorldObject* pSource, Unit *pTarget = NULL); + +/* + TODO: Add more script type classes. + + ChatScript + MailScript + SessionScript + CollisionScript + GroupScript + ArenaTeamScript + GuildScript + +*/ + +/* + Standard procedure when adding new script type classes: + + First of all, define the actual class, and have it inherit from ScriptObject, like so: + + class MyScriptType : public ScriptObject + { + uint32 _someId; + + protected: + + MyScriptType(const char* name, uint32 someId) + : ScriptObject(name), _someId(someId) + { } + + void RegisterSelf(); + + public: + + // If a virtual function in your script type class is not necessarily + // required to be overridden, just declare it virtual with an empty + // body. If, on the other hand, it's logical only to override it (i.e. + // if it's the only method in the class), make it pure virtual, by adding + // = 0 to it. + virtual void OnSomeEvent(uint32 someArg1, std::string& someArg2) { } + + // This is a pure virtual function: + virtual void OnAnotherEvent(uint32 someArg) = 0; + } + + RegisterSelf() should be defined in ScriptMgr.cpp, and simply registers the script + with ScriptRegistry: + + void MyScriptType::RegisterSelf() + { + ScriptMgr::ScriptRegistry<MyScriptType>::AddScript(this); + } + + Next, you need to add a specialization for ScriptRegistry. Put this in the bottom of + ScriptMgr.cpp: + + template class ScriptMgr::ScriptRegistry<MyScriptType>; + + Now, add a cleanup routine in ScriptMgr::~ScriptMgr: + + SCR_CLEAR(MyScriptType); + + Now your script type is good to go with the script system. What you need to do now + is add functions to ScriptMgr that can be called from the core to actually trigger + certain events. For example, in ScriptMgr.h: + + void OnSomeEvent(uint32 someArg1, std::string& someArg2); + void OnAnotherEvent(uint32 someArg); + + In ScriptMgr.cpp: + + void ScriptMgr::OnSomeEvent(uint32 someArg1, std::string& someArg2) + { + FOREACH_SCRIPT(MyScriptType)->OnSomeEvent(someArg1, someArg2); + } + + void ScriptMgr::OnAnotherEvent(uint32 someArg) + { + FOREACH_SCRIPT(MyScriptType)->OnAnotherEvent(someArg1, someArg2); + } + + Now you simply call these two functions from anywhere in the core to trigger the + event on all registered scripts of that type. +*/ + +class ScriptObject +{ + friend class ScriptMgr; + + public: + + // Called when the script is initialized. Use it to initialize any properties of the script. + virtual void OnInitialize() { } + + // Called when the script is deleted. Use it to free memory, etc. + virtual void OnTeardown() { } + + // Do not override this in scripts; it should be overridden by the various script type classes. It indicates + // whether or not this script type must be assigned in the database. + virtual bool IsDatabaseBound() const { return false; } + + const std::string& GetName() const { return _name; } + + const char* ToString() const { return _name.c_str(); } + + protected: + + // Call this to register the script with ScriptMgr. + virtual void RegisterSelf() = 0; + + ScriptObject(const char* name) + : _name(std::string(name)) + { + // Allow the script to do startup routines. + OnInitialize(); + + // Register with ScriptMgr. + RegisterSelf(); + } + + virtual ~ScriptObject() + { + // Allow the script to do cleanup routines. + OnTeardown(); + } + + private: + + const std::string _name; +}; + +template<class TObject> class UpdatableScript +{ + protected: + + UpdatableScript() + { + } + + public: + + virtual void OnUpdate(TObject* obj, uint32 diff) { } +}; + +class SpellHandlerScript : public ScriptObject +{ + protected: + + SpellHandlerScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Should return a fully valid SpellScript pointer. + virtual SpellScript* GetSpellScript() const = 0; +}; + +class AuraHandlerScript : public ScriptObject +{ + protected: + + AuraHandlerScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Should return a fully valid AuraScript pointer. + // virtual AuraScript* GetAuraScript() const = 0; +}; + +class ServerScript : public ScriptObject +{ + protected: + + ServerScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Called when reactive socket I/O is started (WorldSocketMgr). + virtual void OnNetworkStart() { } + + // Called when reactive I/O is stopped. + virtual void OnNetworkStop() { } + + // Called when a remote socket establishes a connection to the server. Do not store the socket object. + virtual void OnSocketOpen(WorldSocket* socket) { } + + // Called when a socket is closed. Do not store the socket object, and do not rely on the connection + // being open; it is not. + virtual void OnSocketClose(WorldSocket* socket, bool wasNew) { } + + // Called when a packet is sent to a client. The packet object is a copy of the original packet, so reading + // and modifying it is safe. + virtual void OnPacketSend(WorldSocket* socket, WorldPacket& packet) { } + + // Called when a (valid) packet is received by a client. The packet object is a copy of the original packet, so + // reading and modifying it is safe. + virtual void OnPacketReceive(WorldSocket* socket, WorldPacket& packet) { } + + // Called when an invalid (unknown opcode) packet is received by a client. The packet is a reference to the orignal + // packet; not a copy. This allows you to actually handle unknown packets (for whatever purpose). + virtual void OnUnknownPacketReceive(WorldSocket* socket, WorldPacket& packet) { } +}; + +class WorldScript : public ScriptObject, public UpdatableScript<void> +{ + protected: + + WorldScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Called when the open/closed state of the world changes. + virtual void OnOpenStateChange(bool open) { } + + // Called after the world configuration is (re)loaded. + virtual void OnConfigLoad(bool reload) { } + + // Called before the message of the day is changed. + virtual void OnMotdChange(std::string& newMotd) { } + + // Called when a world shutdown is initiated. + virtual void OnShutdown(ShutdownExitCode code, ShutdownMask mask) { } + + // Called when a world shutdown is cancelled. + virtual void OnShutdownCancel() { } + + // Called on every world tick (don't execute too heavy code here). + virtual void OnUpdate(void* null, uint32 diff) { } +}; + +class FormulaScript : public ScriptObject +{ + protected: + + FormulaScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Called after calculating honor. + virtual void OnHonorCalculation(float& honor, uint8 level, uint32 count) { } + + // Called after calculating honor. + virtual void OnHonorCalculation(uint32& honor, uint8 level, uint32 count) { } + + // Called after gray level calculation. + virtual void OnGetGrayLevel(uint8& grayLevel, uint8 playerLevel) { } + + // Called after calculating experience color. + virtual void OnGetColorCode(XPColorChar& color, uint8 playerLevel, uint8 mobLevel) { } + + // Called after calculating zero difference. + virtual void OnGetZeroDifference(uint8& diff, uint8 playerLevel) { } + + // Called after calculating base experience gain. + virtual void OnGetBaseGain(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content) { } + + // Called after calculating experience gain. + virtual void OnGetGain(uint32& gain, Player* player, Unit* unit) { } + + virtual void OnGetGroupRate(float& rate, uint32 count, bool isRaid) { } +}; + +template<class TMap> class MapScript : public UpdatableScript<TMap> +{ + MapEntry const* _mapEntry; + + protected: + + MapScript(uint32 mapId) + : _mapEntry(sMapStore.LookupEntry(mapId)) + { + if (!_mapEntry) + sLog.outError("Invalid MapScript for %u; no such map ID.", mapId); + } + + public: + + // Gets the MapEntry structure associated with this script. Can return NULL. + MapEntry const* GetEntry() { return _mapEntry; } + + // Called when the map is created. + virtual void OnCreate(TMap* map) { } + + // Called just before the map is destroyed. + virtual void OnDestroy(TMap* map) { } + + // Called when a grid map is loaded. + virtual void OnLoadGridMap(TMap* map, uint32 gx, uint32 gy) { } + + // Called when a grid map is unloaded. + virtual void OnUnloadGridMap(TMap* map, uint32 gx, uint32 gy) { } + + // Called when a player enters the map. + virtual void OnPlayerEnter(TMap* map, Player* player) { } + + // Called when a player leaves the map. + virtual void OnPlayerLeave(TMap* map, Player* player) { } + + // Called on every map update tick. + virtual void OnUpdate(TMap* map, uint32 diff) { } +}; + +class WorldMapScript : public ScriptObject, public MapScript<Map> +{ + protected: + + WorldMapScript(const char* name, uint32 mapId) + : ScriptObject(name), MapScript(mapId) + { + if (GetEntry() && !GetEntry()->IsContinent()) + sLog.outError("WorldMapScript for map %u is invalid.", mapId); + } + + void RegisterSelf(); +}; + +class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> +{ + protected: + + InstanceMapScript(const char* name, uint32 mapId = 0) + : ScriptObject(name), MapScript(mapId) + { + if (GetEntry() && !GetEntry()->IsDungeon()) + sLog.outError("InstanceMapScript for map %u is invalid.", mapId); + } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Gets an InstanceData object for this instance. + virtual InstanceData* OnGetInstanceData(InstanceMap* map) { return NULL; } +}; + +class BattlegroundMapScript : public ScriptObject, public MapScript<BattleGroundMap> +{ + protected: + + BattlegroundMapScript(const char* name, uint32 mapId) + : ScriptObject(name), MapScript(mapId) + { + if (GetEntry() && !GetEntry()->IsBattleGround()) + sLog.outError("BattlegroundMapScript for map %u is invalid.", mapId); + } + + void RegisterSelf(); +}; + +class ItemScript : public ScriptObject +{ + protected: + + ItemScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when a dummy spell effect is triggered on the item. + virtual bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Item* target) { return false; } + + // Called when a player accepts a quest from the item. + virtual bool OnQuestAccept(Player* player, Item* item, Quest const* quest) { return false; } + + // Called when a player uses the item. + virtual bool OnUse(Player* player, Item* item, SpellCastTargets const& targets) { return false; } + + // Called when the item expires (is destroyed). + virtual bool OnExpire(Player* player, ItemPrototype const* proto) { return false; } +}; + +class CreatureScript : public ScriptObject, public UpdatableScript<Creature> +{ + protected: + + CreatureScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when a dummy spell effect is triggered on the creature. + virtual bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Creature* target) { return false; } + + // Called when a player opens a gossip dialog with the creature. + virtual bool OnGossipHello(Player* player, Creature* creature) { return false; } + + // Called when a player selects a gossip item in the creature's gossip menu. + virtual bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) { return false; } + + // Called when a player selects a gossip with a code in the creature's gossip menu. + virtual bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code) { return false; } + + // Called when a player accepts a quest from the creature. + virtual bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) { return false; } + + // Called when a player selects a quest in the creature's quest menu. + virtual bool OnQuestSelect(Player* player, Creature* creature, Quest const* quest) { return false; } + + // Called when a player completes a quest with the creature. + virtual bool OnQuestComplete(Player* player, Creature* creature, Quest const* quest) { return false; } + + // Called when a player selects a quest reward. + virtual bool OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt) { return false; } + + // Called when the dialog status between a player and the creature is requested. + virtual uint32 OnDialogStatus(Player* player, Creature* creature) { return 0; } + + // Called when a CreatureAI object is needed for the creature. + virtual CreatureAI* OnGetAI() { return NULL; } +}; + +class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> +{ + protected: + + GameObjectScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when a dummy spell effect is triggered on the gameobject. + virtual bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, GameObject* target) { return false; } + + // Called when a player opens a gossip dialog with the gameobject. + virtual bool OnGossipHello(Player* player, GameObject* go) { return false; } + + // Called when a player selects a gossip item in the gameobject's gossip menu. + virtual bool OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) { return false; } + + // Called when a player selects a gossip with a code in the gameobject's gossip menu. + virtual bool OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code) { return false; } + + // Called when a player accepts a quest from the gameobject. + virtual bool OnQuestAccept(Player* player, GameObject* go, Quest const* quest) { return false; } + + // Called when a player selects a quest reward. + virtual bool OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt) { return false; } + + // Called when the dialog status between a player and the gameobject is requested. + virtual uint32 OnDialogStatus(Player* player, GameObject* go) { return 0; } + + // Called when the gameobject is destroyed (destructible buildings only). + virtual void OnDestroyed(Player* player, GameObject* go, uint32 eventId) { } +}; + +class AreaTriggerScript : public ScriptObject +{ + protected: + + AreaTriggerScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when the area trigger is activated by a player. + bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) { return false; } +}; + +class BattlegroundScript : public ScriptObject +{ + protected: + + BattlegroundScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Should return a fully valid BattleGround object for the type ID. + virtual BattleGround* OnGetBattleground() = 0; +}; + +class OutdoorPvPScript : public ScriptObject +{ + protected: + + OutdoorPvPScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Should return a fully valid OutdoorPvP object for the type ID. + virtual OutdoorPvP* OnGetOutdoorPvP() = 0; +}; + +class CommandScript : public ScriptObject +{ + protected: + + CommandScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Should return a pointer to a valid command table (ChatCommand array) to be used by ChatHandler. + virtual ChatCommand* OnGetCommands() = 0; +}; + +class WeatherScript : public ScriptObject, public UpdatableScript<Weather> +{ + protected: + + WeatherScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when the weather changes in the zone this script is associated with. + virtual void OnChange(Weather* weather, WeatherState state, float grade) { } +}; + +class AuctionHouseScript : public ScriptObject +{ + protected: + + AuctionHouseScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Called when an auction is added to an auction house. + void OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry) { } + + // Called when an auction is removed from an auction house. + void OnAuctionRemove(AuctionHouseObject* ah, AuctionEntry* entry) { } + + // Called when an auction was succesfully completed. + void OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry) { } + + // Called when an auction expires. + void OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) { } }; +class ConditionScript : public ScriptObject +{ + protected: + + ConditionScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when a single condition is checked for a player. + bool OnConditionCheck(Condition* condition, Player* player, Unit* targetOverride) { return true; } +}; + +class VehicleScript : public ScriptObject +{ + protected: + + VehicleScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); + + public: + + // Called after a vehicle is installed. + virtual void OnInstall(Vehicle* veh) { } + + // Called after a vehicle is uninstalled. + virtual void OnUninstall(Vehicle* veh) { } + + // Called after a vehicle dies. + virtual void OnDie(Vehicle* veh) { } + + // Called when a vehicle resets. + virtual void OnReset(Vehicle* veh) { } + + // Called after an accessory is installed in a vehicle. + virtual void OnInstallAccessory(Vehicle* veh, Creature* accessory) { } + + // Called after a passenger is added to a vehicle. + virtual void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId) { } + + // Called after a passenger is removed from a vehicle. + virtual void OnRemovePassenger(Vehicle* veh, Unit* passenger) { } +}; + +class DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject> +{ + protected: + + DynamicObjectScript(const char* name) + : ScriptObject(name) + { } + + void RegisterSelf(); +}; + +class TransportScript : public ScriptObject, public UpdatableScript<Transport> +{ + protected: + + TransportScript(const char* name) + : ScriptObject(name) + { + } + + void RegisterSelf(); + + public: + + bool IsDatabaseBound() const { return true; } + + // Called when a player boards the transport. + virtual void OnAddPassenger(Transport* transport, Player* player) { } + + // Called when a creature boards the transport. + virtual void OnAddCreaturePassenger(Transport* transport, Creature* creature) { } + + // Called when a player exits the transport. + virtual void OnRemovePassenger(Transport* transport, Player* player) { } +}; + +// Placed here due to ScriptRegistry::AddScript dependency. +#define sScriptMgr (*ACE_Singleton<ScriptMgr, ACE_Null_Mutex>::instance()) + +// Manages registration, loading, and execution of scripts. class ScriptMgr { friend class ACE_Singleton<ScriptMgr, ACE_Null_Mutex>; + friend class ScriptObject; + ScriptMgr(); - public: - ~ScriptMgr(); - - void ScriptsInit(); - void LoadDatabase(); - char const* ScriptsVersion(); - - //event handlers - void OnLogin(Player *pPlayer); - void OnLogout(Player *pPlayer); - void OnPVPKill(Player *killer, Player *killed); - bool OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell); - uint32 OnGetXP(Player *pPlayer, uint32 amount); - uint32 OnGetMoney(Player *pPlayer, int32 amount); - bool OnPlayerChat(Player *pPlayer, const char *text); - void OnServerStartup(); - void OnServerShutdown(); - void OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea); - bool OnItemClick (Player *pPlayer, Item *pItem); - bool OnItemOpen (Player *pPlayer, Item *pItem); - bool OnGoClick (Player *pPlayer, GameObject *pGameObject); - void OnCreatureKill (Player *pPlayer, Creature *pCreature); - bool GossipHello (Player * pPlayer, Creature* pCreature); - bool GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction); - bool GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode); - bool GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction); - bool GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode); - bool QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt); - uint32 NPCDialogStatus(Player* pPlayer, Creature* pCreature); - uint32 GODialogStatus(Player* pPlayer, GameObject* pGO); - bool ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest); - bool ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest); - bool GOHello(Player* pPlayer, GameObject* pGO); - bool GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest); - bool GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt); - void GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent); - bool AreaTrigger(Player* pPlayer,AreaTriggerEntry const* atEntry); - CreatureAI* GetAI(Creature* pCreature); - bool ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets); - bool ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto); - bool EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget); - bool EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget); - bool EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget); - InstanceData* CreateInstanceData(Map *map); - void CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & script_vector); - void CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > & script_vector); -}; - -//Generic scripting text function -void DoScriptText(int32 textEntry, WorldObject* pSource, Unit *pTarget = NULL); + ~ScriptMgr(); -#define sScriptMgr (*ACE_Singleton<ScriptMgr, ACE_Null_Mutex>::instance()) -#endif + uint32 _scriptCount; + + void LoadDatabase(); + void FillSpellSummary(); + + public: /* Initialization */ + + void Initialize(); + const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; } + + void IncrementScriptCount() { ++_scriptCount; } + uint32 GetScriptCount() const { return _scriptCount; } + + public: /* SpellHandlerScript */ + + void CreateSpellScripts(uint32 spell_id, std::list<SpellScript*>& script_vector); + void CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript*, SpellScriptsMap::iterator> >& script_vector); + + public: /* AuraHandlerScript */ + + // void CreateAuraScripts(uint32 spell_id, std::list<AuraScript*>& script_vector); + // void CreateAuraScripts(uint32 spell_id, std::vector<std::pair<AuraScript*, SpellScriptsMap::iterator> >& script_vector); + + public: /* ServerScript */ + + void OnNetworkStart(); + void OnNetworkStop(); + void OnSocketOpen(WorldSocket* socket); + void OnSocketClose(WorldSocket* socket, bool wasNew); + void OnPacketReceive(WorldSocket* socket, WorldPacket& packet); + void OnPacketSend(WorldSocket* socket, WorldPacket& packet); + void OnUnknownPacketReceive(WorldSocket* socket, WorldPacket& packet); + + public: /* WorldScript */ + + void OnOpenStateChange(bool open); + void OnConfigLoad(bool reload); + void OnMotdChange(std::string& newMotd); + void OnShutdown(ShutdownExitCode code, ShutdownMask mask); + void OnShutdownCancel(); + void OnWorldUpdate(uint32 diff); + + public: /* FormulaScript */ + void OnHonorCalculation(float& honor, uint8 level, uint32 count); + void OnHonorCalculation(uint32& honor, uint8 level, uint32 count); + void OnGetGrayLevel(uint8& grayLevel, uint8 playerLevel); + void OnGetColorCode(XPColorChar& color, uint8 playerLevel, uint8 mobLevel); + void OnGetZeroDifference(uint8& diff, uint8 playerLevel); + void OnGetBaseGain(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content); + void OnGetGain(uint32& gain, Player* player, Unit* unit); + void OnGetGroupRate(float& rate, uint32 count, bool isRaid); + + public: /* MapScript */ + + void OnCreateMap(Map* map); + void OnDestroyMap(Map* map); + void OnLoadGridMap(Map* map, uint32 gx, uint32 gy); + void OnUnloadGridMap(Map* map, uint32 gx, uint32 gy); + void OnPlayerEnter(Map* map, Player* player); + void OnPlayerLeave(Map* map, Player* player); + void OnMapUpdate(Map* map, uint32 diff); + + public: /* InstanceMapScript */ + + InstanceData* CreateInstanceData(InstanceMap* map); + + public: /* ItemScript */ + + bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Item* target); + bool OnQuestAccept(Player* player, Item* item, Quest const* quest); + bool OnItemUse(Player* player, Item* item, SpellCastTargets const& targets); + bool OnItemExpire(Player* player, ItemPrototype const* proto); + + public: /* CreatureScript */ + + bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Creature* target); + bool OnGossipHello(Player* player, Creature* creature); + bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action); + bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code); + bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest); + bool OnQuestSelect(Player* player, Creature* creature, Quest const* quest); + bool OnQuestComplete(Player* player, Creature* creature, Quest const* quest); + bool OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt); + uint32 GetDialogStatus(Player* player, Creature* creature); + CreatureAI* GetCreatureAI(Creature* creature); + void OnCreatureUpdate(Creature* creature, uint32 diff); + + public: /* GameObjectScript */ + + bool OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, GameObject* target); + bool OnGossipHello(Player* player, GameObject* go); + bool OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action); + bool OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code); + bool OnQuestAccept(Player* player, GameObject* go, Quest const* quest); + bool OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt); + uint32 GetDialogStatus(Player* player, GameObject* go); + void OnGameObjectDestroyed(Player* player, GameObject* go, uint32 eventId); + void OnGameObjectUpdate(GameObject* go, uint32 diff); + + public: /* AreaTriggerScript */ + + bool OnTrigger(Player* player, AreaTriggerEntry const* trigger); + + public: /* BattlegroundScript */ + + BattleGround* CreateBattleground(BattleGroundTypeId typeId); + + public: /* OutdoorPvPScript */ + + OutdoorPvP* CreateOutdoorPvP(OutdoorPvPData const* data); + + public: /* CommandScript */ + + std::vector<ChatCommand*> GetChatCommands(); + + public: /* WeatherScript */ + + void OnWeatherChange(Weather* weather, WeatherState state, float grade); + void OnWeatherUpdate(Weather* weather, uint32 diff); + + public: /* AuctionHouseScript */ + + void OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry); + void OnRemoveAuction(AuctionHouseObject* ah, AuctionEntry* entry); + void OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry); + void OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry); + + public: /* ConditionScript */ + + bool OnConditionCheck(Condition* condition, Player* player, Unit* targetOverride); + + public: /* VehicleScript */ + + void OnInstall(Vehicle* veh); + void OnUninstall(Vehicle* veh); + void OnDie(Vehicle* veh); + void OnReset(Vehicle* veh); + void OnInstallAccessory(Vehicle* veh, Creature* accessory); + void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId); + void OnRemovePassenger(Vehicle* veh, Unit* passenger); + + public: /* DynamicObjectScript */ + + void OnDynamicObjectUpdate(DynamicObject* dynobj, uint32 diff); + + public: /* TransportScript */ + + void OnAddPassenger(Transport* transport, Player* player); + void OnAddCreaturePassenger(Transport* transport, Creature* creature); + void OnRemovePassenger(Transport* transport, Player* player); + void OnTransportUpdate(Transport* transport, uint32 diff); + + public: /* ScriptRegistry */ + + // This is the global static registry of scripts. + template<class TScript> class ScriptRegistry + { + // Counter used for code-only scripts. + static uint32 _scriptIdCounter; + + public: + + typedef std::map<uint32, TScript*> ScriptMap; + + // The actual list of scripts. This will be accessed concurrently, so it must not be modified + // after server startup. + static ScriptMap ScriptPointerList; + + // Gets a script by its ID (assigned by ObjectMgr). + static TScript* GetScriptById(uint32 id) + { + for (ScriptMap::iterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) + if (it->first == id) + return it->second; + + return NULL; + } + + // Attempts to add a new script to the list. + static void AddScript(TScript* const script); + }; +}; + +#endif diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h index 7102e4a43e1..52401502c83 100644 --- a/src/server/game/Scripting/ScriptSystem.h +++ b/src/server/game/Scripting/ScriptSystem.h @@ -97,6 +97,6 @@ class SystemMgr PointMoveMap m_mPointMoveMap; //coordinates for waypoints }; -#define pSystemMgr SystemMgr::Instance() +#define sScriptSystemMgr SystemMgr::Instance() #endif |
