/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "ScriptMgr.h" #include "InstanceScript.h" #include "ScriptSystem.h" #include "SmartAI.h" #include "SpellMgr.h" #include "UnitAI.h" namespace { template inline void SCR_CLEAR() { for (auto const& [scriptID, script] : ScriptRegistry::ScriptPointerList) { delete script; } ScriptRegistry::ScriptPointerList.clear(); } } struct TSpellSummary { uint8 Targets; // set of enum SelectTarget uint8 Effects; // set of enum SelectEffect }*SpellSummary; ScriptMgr::ScriptMgr() : _scriptCount(0), _scheduledScripts(0), _script_loader_callback(nullptr), _modules_loader_callback(nullptr) { } ScriptMgr::~ScriptMgr() { } ScriptMgr* ScriptMgr::instance() { static ScriptMgr instance; return &instance; } void ScriptMgr::Initialize() { LOG_INFO("server.loading", "> Loading C++ scripts"); LOG_INFO("server.loading", " "); AddSC_SmartScripts(); ASSERT(_script_loader_callback, "Script loader callback wasn't registered!"); ASSERT(_modules_loader_callback, "Modules loader callback wasn't registered!"); _script_loader_callback(); _modules_loader_callback(); } void ScriptMgr::Unload() { SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); delete[] SpellSummary; } void ScriptMgr::LoadDatabase() { uint32 oldMSTime = getMSTime(); sScriptSystemMgr->LoadScriptWaypoints(); // Add all scripts that must be loaded after db/maps ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); ScriptRegistry::AddALScripts(); FillSpellSummary(); CheckIfScriptsInDatabaseExist(); LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } void ScriptMgr::CheckIfScriptsInDatabaseExist() { for (auto const& scriptName : sObjectMgr->GetScriptNames()) { if (uint32 sid = sObjectMgr->GetScriptId(scriptName.c_str())) { if (!ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid)) { LOG_ERROR("sql.sql", "Script named '%s' is assigned in the database, but has no code!", scriptName.c_str()); } } } } void ScriptMgr::FillSpellSummary() { UnitAI::FillAISpellInfo(); SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()]; SpellInfo const* pTempSpell; for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) { SpellSummary[i].Effects = 0; SpellSummary[i].Targets = 0; pTempSpell = sSpellMgr->GetSpellInfo(i); // This spell doesn't exist. if (!pTempSpell) continue; for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { // Spell targets self. if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF - 1); // Spell targets a single enemy. if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY - 1); // Spell targets AoE at enemy. if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY - 1); // Spell targets an enemy. if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY - 1); // Spell targets a single friend (or self). if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND - 1); // Spell targets AoE friends. if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND - 1); // Spell targets any friend (or self). if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND - 1); // Make sure that this spell includes a damage effect. if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE || pTempSpell->Effects[j].Effect == SPELL_EFFECT_INSTAKILL || pTempSpell->Effects[j].Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || pTempSpell->Effects[j].Effect == 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->Effects[j].Effect == SPELL_EFFECT_HEAL || pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MECHANICAL || (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && pTempSpell->Effects[j].ApplyAuraName == 8)) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING - 1); // Make sure that this spell applies an aura. if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA - 1); } } } ///- AllMapScript::AllMapScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AllCreatureScript::AllCreatureScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } UnitScript::UnitScript(const char* name, bool addToScripts) : ScriptObject(name) { if (addToScripts) ScriptRegistry::AddScript(this); } MovementHandlerScript::MovementHandlerScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } SpellScriptLoader::SpellScriptLoader(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ServerScript::ServerScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } WorldScript::WorldScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } FormulaScript::FormulaScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } WorldMapScript::WorldMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript(mapId) { ScriptRegistry::AddScript(this); } InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript(mapId) { ScriptRegistry::AddScript(this); } BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript(mapId) { ScriptRegistry::AddScript(this); } ItemScript::ItemScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } CreatureScript::CreatureScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } GameObjectScript::GameObjectScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AreaTriggerScript::AreaTriggerScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } bool OnlyOnceAreaTriggerScript::OnTrigger(Player* player, AreaTrigger const* trigger) { uint32 const triggerId = trigger->entry; if (InstanceScript* instance = player->GetInstanceScript()) { if (instance->IsAreaTriggerDone(triggerId)) { return true; } else { instance->MarkAreaTriggerDone(triggerId); } } return _OnTrigger(player, trigger); } void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(InstanceScript* script, uint32 triggerId) { script->ResetAreaTriggerDone(triggerId); } void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(Player const* player, AreaTrigger const* trigger) { if (InstanceScript* instance = player->GetInstanceScript()) { ResetAreaTriggerDone(instance, trigger->entry); } } BattlegroundScript::BattlegroundScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } OutdoorPvPScript::OutdoorPvPScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } CommandScript::CommandScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } WeatherScript::WeatherScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AuctionHouseScript::AuctionHouseScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ConditionScript::ConditionScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } VehicleScript::VehicleScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } DynamicObjectScript::DynamicObjectScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } TransportScript::TransportScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AchievementCriteriaScript::AchievementCriteriaScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } PlayerScript::PlayerScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AccountScript::AccountScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } GuildScript::GuildScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } GroupScript::GroupScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } GlobalScript::GlobalScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } BGScript::BGScript(char const* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ArenaTeamScript::ArenaTeamScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } SpellSC::SpellSC(char const* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ModuleScript::ModuleScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } GameEventScript::GameEventScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } MailScript::MailScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AchievementScript::AchievementScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } PetScript::PetScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ArenaScript::ArenaScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } MiscScript::MiscScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } CommandSC::CommandSC(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } DatabaseScript::DatabaseScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } WorldObjectScript::WorldObjectScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } LootScript::LootScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } ElunaScript::ElunaScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AllItemScript::AllItemScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } AllGameObjectScript::AllGameObjectScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); } // Specialize for each script type class like so: template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry; template class AC_GAME_API ScriptRegistry;