diff --git a/sql/base/mangos.sql b/sql/base/mangos.sql index a6fb95f93f..211ced4781 100644 --- a/sql/base/mangos.sql +++ b/sql/base/mangos.sql @@ -455,6 +455,10 @@ INSERT INTO `command` VALUES ('debug arena',3,'Syntax: .debug arena\r\n\r\nToggle debug mode for arenas. In debug mode GM can start arena with single player.'), ('debug areatriggers', 1, 'Syntax: .debug areatriggers\n\nToggle debug mode for areatriggers. In debug mode GM will be notified if reaching an areatrigger.'), ('debug bg',3,'Syntax: .debug bg\r\n\r\nToggle debug mode for battlegrounds. In debug mode GM can start battleground with single player.'), +('debug dbscript',3,'.debug dbscript\r\n\r\nStarts dbscript type param0 id param1 from player(source) to selected(target)'), +('debug dbscripttargeted',3,'.debug dbscript\r\n\r\nStarts dbscript type param0 id param1 from selected(source) to param2 dbguid(target creature)'), +('debug dbscriptsourced',3,'.debug dbscript\r\n\r\nStarts dbscript type param0 id param1 from param2 dbguid(source creature) to selected(target)'), +('debug dbscriptguided',3,'.debug dbscript\r\n\r\nStarts dbscript type param0 id param1 from param2 dbguid(source creature) to param3 dbguid(target creature)'), ('debug getitemvalue',3,'Syntax: .debug getitemvalue #itemguid #field [int|hex|bit|float]\r\n\r\nGet the field #field of the item #itemguid in your inventroy.\r\n\r\nUse type arg for set output format: int (decimal number), hex (hex value), bit (bitstring), float. By default use integer output.'), ('debug getvaluebyindex', 3, 'Syntax: .debug getvaluebyindex #field [int|hex|bit|float]\r\n\r\nGet the field index #field (integer) of the selected target. If no target is selected, get the content of your field.\r\n\r\nUse type arg for set output format: int (decimal number), hex (hex value), bit (bitstring), float. By default use integer output.'), ('debug getvaluebyname', 3, 'Syntax: .debug getvaluebyname #field [int|hex|bit|float]\r\n\r\nGet the field name #field (string) of the selected target. If no target is selected, get the content of your field.\r\n\r\nUse type arg for set output format: int (decimal number), hex (hex value), bit (bitstring), float. By default use integer output.'), diff --git a/src/game/AI/BaseAI/UnitAI.cpp b/src/game/AI/BaseAI/UnitAI.cpp index 9b10762171..46171c46aa 100644 --- a/src/game/AI/BaseAI/UnitAI.cpp +++ b/src/game/AI/BaseAI/UnitAI.cpp @@ -1226,7 +1226,7 @@ void UnitAI::UpdateSpellLists() success = true; OnSpellCast(sSpellTemplate.LookupEntry(spellId), target); if (scriptId) - m_unit->GetMap()->ScriptsStart(sRelayScripts, scriptId, m_unit, target); + m_unit->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, scriptId, m_unit, target); break; } itr = eligibleSpells.erase(itr); diff --git a/src/game/AI/EventAI/CreatureEventAI.cpp b/src/game/AI/EventAI/CreatureEventAI.cpp index 90a84dfa1b..d3001bb695 100644 --- a/src/game/AI/EventAI/CreatureEventAI.cpp +++ b/src/game/AI/EventAI/CreatureEventAI.cpp @@ -1279,10 +1279,10 @@ bool CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 uint32 relayId = sScriptMgr.GetRandomRelayDbscriptFromTemplate(uint32(-action.relayScript.relayId)); if (relayId == 0) break; - m_creature->GetMap()->ScriptsStart(sRelayScripts, relayId, target, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, relayId, target, m_creature); } else - m_creature->GetMap()->ScriptsStart(sRelayScripts, action.relayScript.relayId, target, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, action.relayScript.relayId, target, m_creature); break; } case ACTION_T_TEXT_NEW: diff --git a/src/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/game/AI/EventAI/CreatureEventAIMgr.cpp index 73150231ee..cf296b0b1d 100644 --- a/src/game/AI/EventAI/CreatureEventAIMgr.cpp +++ b/src/game/AI/EventAI/CreatureEventAIMgr.cpp @@ -957,7 +957,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() case ACTION_T_START_RELAY_SCRIPT: if (action.relayScript.relayId > 0) { - if (sRelayScripts.second.find(action.relayScript.relayId) == sRelayScripts.second.end()) + auto relayScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_RELAY); + if (relayScripts->second.find(action.relayScript.relayId) == relayScripts->second.end()) { sLog.outErrorEventAI("Event %u Action %u references invalid dbscript_on_relay id %u", eventId, j + 1, action.relayScript.relayId); } diff --git a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/isle_of_queldanas.cpp b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/isle_of_queldanas.cpp index 40f4c2817d..50c9197a33 100644 --- a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/isle_of_queldanas.cpp +++ b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/isle_of_queldanas.cpp @@ -147,7 +147,7 @@ struct npc_shattered_sun_fighterAI : public ScriptedAI } } if (transformScriptId) - m_creature->GetMap()->ScriptsStart(sRelayScripts, transformScriptId, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, transformScriptId, m_creature, m_creature); } } diff --git a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp index c9019a4191..2bcb8d6ec0 100644 --- a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp +++ b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp @@ -206,7 +206,7 @@ struct boss_scarlet_commander_mograineAI : public CombatAI { if (m_instance->GetData(TYPE_ASHBRINGER_EVENT) == IN_PROGRESS) { - pWho->GetMap()->ScriptsStart(sRelayScripts, ASHBRINGER_RELAY_SCRIPT_ID, m_creature, pWho); + pWho->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, ASHBRINGER_RELAY_SCRIPT_ID, m_creature, pWho); m_instance->SetData(TYPE_ASHBRINGER_EVENT, DONE); } } diff --git a/src/game/AI/ScriptDevAI/scripts/kalimdor/dire_maul/dire_maul.cpp b/src/game/AI/ScriptDevAI/scripts/kalimdor/dire_maul/dire_maul.cpp index 035fc3e194..2dff6cff88 100644 --- a/src/game/AI/ScriptDevAI/scripts/kalimdor/dire_maul/dire_maul.cpp +++ b/src/game/AI/ScriptDevAI/scripts/kalimdor/dire_maul/dire_maul.cpp @@ -111,7 +111,7 @@ struct npc_warlock_mount_ritualAI : public Scripted_NoMovementAI void DoSummonPack(uint8 uiIndex) { - m_creature->GetMap()->ScriptsStart(sRelayScripts, SUMMON_WAVES_RELAY_SCRIPT_START_ID + uiIndex, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, SUMMON_WAVES_RELAY_SCRIPT_START_ID + uiIndex, m_creature, m_creature); m_pInstance->DoRespawnGameObject(m_pInstance->GetRitualSymbolGuids().at(uiIndex - 1), 900); } diff --git a/src/game/AI/ScriptDevAI/scripts/kalimdor/dustwallow_marsh.cpp b/src/game/AI/ScriptDevAI/scripts/kalimdor/dustwallow_marsh.cpp index 6174dd7e9e..4cc3420f20 100644 --- a/src/game/AI/ScriptDevAI/scripts/kalimdor/dustwallow_marsh.cpp +++ b/src/game/AI/ScriptDevAI/scripts/kalimdor/dustwallow_marsh.cpp @@ -1334,7 +1334,7 @@ bool QuestAccept_npc_major_mills(Player* player, Creature* creature, const Quest { if (npc_major_mills* ai = static_cast(creature->AI())) ai->m_playerGuid = player->GetObjectGuid(); - creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_RELAY_TAKE_DOWN_TETHYR, creature, player); + creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_RELAY_TAKE_DOWN_TETHYR, creature, player); } } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/blades_edge_mountains.cpp b/src/game/AI/ScriptDevAI/scripts/outland/blades_edge_mountains.cpp index 7a74600bfb..511f67a4c0 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/blades_edge_mountains.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/blades_edge_mountains.cpp @@ -2438,7 +2438,7 @@ bool QuestRewarded_into_the_soulgrinder(Player* player, Creature* pCreature, Que { DoScriptText(SAY_MOGDORG_1, pCreature, player); player->CastSpell(player, SPELL_OGRE_FORCE_REACTION, TRIGGERED_OLD_TRIGGERED); - player->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_SPAWN_OGRES, player, pCreature); + player->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_SPAWN_OGRES, player, pCreature); } return true; @@ -2965,7 +2965,7 @@ struct npc_evergrove_druidAI : public ScriptedAI m_creature->SetLevitate(true); m_creature->SetHover(false); m_creature->SetCanFly(false); - m_creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_LANDING_SCRIPT, m_creature, who); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_LANDING_SCRIPT, m_creature, who); } } @@ -2980,7 +2980,7 @@ struct npc_evergrove_druidAI : public ScriptedAI returnTimer = 0; Unit* summoned = m_creature->GetMap()->GetUnit(m_summonerGuid); - m_creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_FLY_OFF_SCRIPT, m_creature, summoned); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_FLY_OFF_SCRIPT, m_creature, summoned); } void ReceiveAIEvent(AIEventType eventType, Unit* sender, Unit* /*invoker*/, uint32 /*miscValue*/) override diff --git a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_peninsula.cpp b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_peninsula.cpp index ff71b47d59..4a9c3fd6f5 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_peninsula.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_peninsula.cpp @@ -423,7 +423,7 @@ struct npc_wounded_blood_elfAI : public npc_escortAI break; case 41: pPlayer->RewardPlayerAndGroupAtEventExplored(QUEST_ROAD_TO_FALCON_WATCH, m_creature); - pPlayer->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_END_TALERIS_INT, m_creature, m_creature); + pPlayer->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_END_TALERIS_INT, m_creature, m_creature); break; } } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/shattrath_city.cpp b/src/game/AI/ScriptDevAI/scripts/outland/shattrath_city.cpp index 0adb2b4fbd..f12d5e3f96 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/shattrath_city.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/shattrath_city.cpp @@ -692,7 +692,7 @@ bool QuestRewarded_npc_adal(Player* player, Creature* creature, Quest const* que break; case QUEST_KAELTHAS_AND_THE_VERDANT_SPHERE: sWorldState.HandleExternalEvent(CUSTOM_EVENT_ADALS_SONG_OF_BATTLE, 0); - player->GetMap()->ScriptsStart(sRelayScripts, SCRIPT_RELAY_ID, creature, player, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); // only once active per adal + player->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, SCRIPT_RELAY_ID, creature, player, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); // only once active per adal return true; // handled } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/terokkar_forest.cpp b/src/game/AI/ScriptDevAI/scripts/outland/terokkar_forest.cpp index b9984effe1..4697b830d3 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/terokkar_forest.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/terokkar_forest.cpp @@ -1310,7 +1310,7 @@ struct npc_draenei_tomb_guardian : public ScriptedAI //m_creature->RemoveGuardians(); // Despawn Bone Wastes - Orb Waypoint 01, Bone Wastes - Event Trigger B, Nether Cloud - m_creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_EVENT_RESET, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_EVENT_RESET, m_creature, m_creature); // Despawn Vengeful Harbinger and Vengeful Draenei for (ObjectGuid &guid : summons) @@ -1351,7 +1351,7 @@ struct npc_draenei_tomb_guardian : public ScriptedAI if (uiMovementType == POINT_MOTION_TYPE && uiData == POINT_HARBINGER_POSITION && harbinger) { m_creature->CastSpell(harbinger, SPELL_COSMETIC_CHAIN_LIGHTNING, TRIGGERED_OLD_TRIGGERED); - m_creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_TOMB_GUARDIAN, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_TOMB_GUARDIAN, m_creature, m_creature); } } }; @@ -1491,7 +1491,7 @@ struct npc_vengeful_harbinger : public ScriptedAI m_creature->ClearAllReactives(); m_creature->GetMotionMaster()->Clear(false, true); m_creature->GetMotionMaster()->MoveIdle(); - m_creature->GetMap()->ScriptsStart(sRelayScripts, DBSCRIPT_VENGEFUL_HARBINGER_FAKE_DEATH, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, DBSCRIPT_VENGEFUL_HARBINGER_FAKE_DEATH, m_creature, m_creature); } }; diff --git a/src/game/AI/ScriptDevAI/scripts/outland/world_outland.cpp b/src/game/AI/ScriptDevAI/scripts/outland/world_outland.cpp index a23f34a46a..40556c3787 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/world_outland.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/world_outland.cpp @@ -836,7 +836,7 @@ struct world_map_outland : public ScriptedMap, public TimerManager { if (GameObject* go = GetSingleGameObjectFromStorage(GO_BASHIR_CRYSTALFORGE, true)) if (Creature* controller = GetClosestCreatureWithEntry(go, CRYSTALFORGE_SLAVE_EVENT_CONTROLLER_ENTRY, 10.f)) - instance->ScriptsStart(sRelayScripts, CRYSTALFORGE_SLAVE_EVENT_RELAY_ID, controller, controller); + instance->ScriptsStart(SCRIPT_TYPE_RELAY, CRYSTALFORGE_SLAVE_EVENT_RELAY_ID, controller, controller); } void HandleBashirSpawnEnemy() diff --git a/src/game/AI/ScriptDevAI/scripts/outland/zangarmarsh.cpp b/src/game/AI/ScriptDevAI/scripts/outland/zangarmarsh.cpp index ec3fb71b8f..d87bbc7754 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/zangarmarsh.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/zangarmarsh.cpp @@ -209,7 +209,7 @@ struct StormcrowAmulet : public AuraScript { if (Creature* ysiel = scriptedMap->GetSingleCreatureFromStorage(NPC_YSIEL_WINDSINGER)) { - caster->GetMap()->ScriptsStart(sRelayScripts, RELAY_SCRIPT_CROW_FLIES, ysiel, caster); + caster->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, RELAY_SCRIPT_CROW_FLIES, ysiel, caster); } } } diff --git a/src/game/AI/ScriptDevAI/scripts/world/midsummer_festival.cpp b/src/game/AI/ScriptDevAI/scripts/world/midsummer_festival.cpp index 8ea4fc31fe..5db4d0353c 100644 --- a/src/game/AI/ScriptDevAI/scripts/world/midsummer_festival.cpp +++ b/src/game/AI/ScriptDevAI/scripts/world/midsummer_festival.cpp @@ -158,8 +158,8 @@ struct RevelerApplauseCheer : public SpellScript { caster->SetFacingToObject(spell->GetUnitTarget()); target->SetFacingToObject(caster); - caster->GetMap()->ScriptsStart(sRelayScripts, RELAY_SCRIPT_ID_DELAY_RESET_ORIENTATION, caster, caster); - target->GetMap()->ScriptsStart(sRelayScripts, RELAY_SCRIPT_ID_DELAY_RESET_ORIENTATION, target, target); + caster->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, RELAY_SCRIPT_ID_DELAY_RESET_ORIENTATION, caster, caster); + target->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, RELAY_SCRIPT_ID_DELAY_RESET_ORIENTATION, target, target); caster->HandleEmote(EMOTE_ONESHOT_BOW); } } diff --git a/src/game/AI/ScriptDevAI/scripts/world/quest_scripts.cpp b/src/game/AI/ScriptDevAI/scripts/world/quest_scripts.cpp index ce79c353da..241137cc9b 100644 --- a/src/game/AI/ScriptDevAI/scripts/world/quest_scripts.cpp +++ b/src/game/AI/ScriptDevAI/scripts/world/quest_scripts.cpp @@ -262,7 +262,7 @@ struct npc_xiri : public ScriptedAI void RunAkamaRPEvent() { - m_creature->GetMap()->ScriptsStart(sRelayScripts, RELAY_SCRIPT_AKAMA, m_creature, m_creature); + m_creature->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, RELAY_SCRIPT_AKAMA, m_creature, m_creature); m_bAkamaInteractionPerformed = true; } diff --git a/src/game/Chat/Chat.cpp b/src/game/Chat/Chat.cpp index d353a99e14..785ad8ea15 100644 --- a/src/game/Chat/Chat.cpp +++ b/src/game/Chat/Chat.cpp @@ -273,6 +273,9 @@ ChatCommand* ChatHandler::getCommandTable() { "debugflags", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugObjectFlags, "", nullptr }, { "packetlog", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugPacketLog, "", nullptr }, { "dbscript", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugDbscript, "", nullptr }, + { "dbscripttargeted", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugDbscriptTargeted, "", nullptr }, + { "dbscriptsourced", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugDbscriptSourced, "", nullptr }, + { "dbscriptguided", SEC_ADMINISTRATOR, true, &ChatHandler::HandleDebugDbscriptGuided, "", nullptr }, { nullptr, 0, false, nullptr, "", nullptr } }; diff --git a/src/game/Chat/Chat.h b/src/game/Chat/Chat.h index a06ef3e60a..bf474bb690 100644 --- a/src/game/Chat/Chat.h +++ b/src/game/Chat/Chat.h @@ -317,6 +317,9 @@ class ChatHandler bool HandleDebugPacketLog(char* args); bool HandleDebugDbscript(char* args); + bool HandleDebugDbscriptTargeted(char* args); + bool HandleDebugDbscriptSourced(char* args); + bool HandleDebugDbscriptGuided(char* args); bool HandleSD2HelpCommand(char* args); bool HandleSD2ScriptCommand(char* args); diff --git a/src/game/Chat/Level3.cpp b/src/game/Chat/Level3.cpp index 3f0bea9bc0..7d12670e7b 100644 --- a/src/game/Chat/Level3.cpp +++ b/src/game/Chat/Level3.cpp @@ -243,13 +243,6 @@ bool ChatHandler::HandleReloadAllQuestCommand(char* /*args*/) bool ChatHandler::HandleReloadAllScriptsCommand(char* /*args*/) { - if (sScriptMgr.IsScriptScheduled()) - { - PSendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - sLog.outString("Re-Loading Scripts..."); HandleReloadDBScriptsOnCreatureDeathCommand((char*)"a"); HandleReloadDBScriptsOnGoUseCommand((char*)"a"); @@ -830,17 +823,10 @@ bool ChatHandler::HandleReloadEventAIScriptsCommand(char* /*args*/) bool ChatHandler::HandleReloadDBScriptsOnGossipCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_gossip`..."); - sScriptMgr.LoadGossipScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GOSSIP, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_gossip` reloaded."); @@ -850,17 +836,10 @@ bool ChatHandler::HandleReloadDBScriptsOnGossipCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnSpellCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_spell`..."); - sScriptMgr.LoadSpellScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_SPELL, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_spell` reloaded."); @@ -870,17 +849,10 @@ bool ChatHandler::HandleReloadDBScriptsOnSpellCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnQuestStartCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_quest_start`..."); - sScriptMgr.LoadQuestStartScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_QUEST_START, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_quest_start` reloaded."); @@ -890,17 +862,10 @@ bool ChatHandler::HandleReloadDBScriptsOnQuestStartCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnQuestEndCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_quest_end`..."); - sScriptMgr.LoadQuestEndScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_QUEST_END, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_quest_end` reloaded."); @@ -910,17 +875,10 @@ bool ChatHandler::HandleReloadDBScriptsOnQuestEndCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnEventCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_event`..."); - sScriptMgr.LoadEventScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_EVENT, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_event` reloaded."); @@ -930,18 +888,11 @@ bool ChatHandler::HandleReloadDBScriptsOnEventCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnGoUseCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_go[_template]_use`..."); - sScriptMgr.LoadGameObjectScripts(); - sScriptMgr.LoadGameObjectTemplateScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GAMEOBJECT, true); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GAMEOBJECT_TEMPLATE, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_go[_template]_use` reloaded."); @@ -951,17 +902,10 @@ bool ChatHandler::HandleReloadDBScriptsOnGoUseCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_creature_death`..."); - sScriptMgr.LoadCreatureDeathScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_CREATURE_DEATH, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_creature_death` reloaded."); @@ -971,17 +915,10 @@ bool ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand(char* args) bool ChatHandler::HandleReloadDBScriptsOnRelayCommand(char* args) { - if (sScriptMgr.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - if (*args != 'a') sLog.outString("Re-Loading Scripts from `dbscripts_on_relay`..."); - sScriptMgr.LoadRelayScripts(); + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_RELAY, true); if (*args != 'a') SendGlobalSysMessage("DB table `dbscripts_on_relay` reloaded."); diff --git a/src/game/Chat/debugcmds.cpp b/src/game/Chat/debugcmds.cpp index 2f3c7ea30c..bd7e2b4cf1 100644 --- a/src/game/Chat/debugcmds.cpp +++ b/src/game/Chat/debugcmds.cpp @@ -1890,14 +1890,103 @@ bool ChatHandler::HandleDebugPacketLog(char* args) bool ChatHandler::HandleDebugDbscript(char* args) { Unit* target = getSelectedUnit(); + uint32 scriptType; + if (!ExtractUInt32(&args, scriptType) || scriptType > SCRIPT_TYPE_INTERNAL) + return false; + + uint32 chosenId; + if (!ExtractUInt32(&args, chosenId)) + return false; + + Player* player = GetSession()->GetPlayer(); + if (!player || !player->IsInWorld()) + return false; + + player->GetMap()->ScriptsStart(ScriptMapType(scriptType), chosenId, player, target); + return true; +} + +bool ChatHandler::HandleDebugDbscriptTargeted(char* args) +{ + Unit* source = getSelectedUnit(); + uint32 scriptType; + if (!ExtractUInt32(&args, scriptType) || scriptType > SCRIPT_TYPE_INTERNAL) + return false; + uint32 chosenId; if (!ExtractUInt32(&args, chosenId)) return false; + uint32 dbGuidTarget; + if (!ExtractUInt32(&args, dbGuidTarget)) + return false; + Player* player = GetSession()->GetPlayer(); if (!player || !player->IsInWorld()) return false; - player->GetMap()->ScriptsStart(sRelayScripts, chosenId, player, target); + Creature* target = player->GetMap()->GetCreature(dbGuidTarget); + if (!source || !target) + return false; + + player->GetMap()->ScriptsStart(ScriptMapType(scriptType), chosenId, source, target); + return true; +} + +bool ChatHandler::HandleDebugDbscriptSourced(char* args) +{ + Unit* target = getSelectedUnit(); + uint32 scriptType; + if (!ExtractUInt32(&args, scriptType) || scriptType > SCRIPT_TYPE_INTERNAL) + return false; + + uint32 chosenId; + if (!ExtractUInt32(&args, chosenId)) + return false; + + uint32 dbGuidSource; + if (!ExtractUInt32(&args, dbGuidSource)) + return false; + + Player* player = GetSession()->GetPlayer(); + if (!player || !player->IsInWorld()) + return false; + + Creature* source = player->GetMap()->GetCreature(dbGuidSource); + if (!source || !target) + return false; + + player->GetMap()->ScriptsStart(ScriptMapType(scriptType), chosenId, source, target); + return true; +} + +bool ChatHandler::HandleDebugDbscriptGuided(char* args) +{ + uint32 scriptType; + if (!ExtractUInt32(&args, scriptType) || scriptType > SCRIPT_TYPE_INTERNAL) + return false; + + uint32 chosenId; + if (!ExtractUInt32(&args, chosenId)) + return false; + + uint32 dbGuidSource; + if (!ExtractUInt32(&args, dbGuidSource)) + return false; + + uint32 dbGuidTarget; + if (!ExtractUInt32(&args, dbGuidTarget)) + return false; + + Player* player = GetSession()->GetPlayer(); + if (!player || !player->IsInWorld()) + return false; + + Creature* source = player->GetMap()->GetCreature(dbGuidSource); + Creature* target = player->GetMap()->GetCreature(dbGuidTarget); + if (!source || !target) + return false; + + player->GetMap()->ScriptsStart(ScriptMapType(scriptType), chosenId, source, target); return true; } diff --git a/src/game/DBScripts/ScriptMgr.cpp b/src/game/DBScripts/ScriptMgr.cpp index d8a2e80d31..51a9ca9369 100644 --- a/src/game/DBScripts/ScriptMgr.cpp +++ b/src/game/DBScripts/ScriptMgr.cpp @@ -36,22 +36,27 @@ #include "Entities/Object.h" #include "Entities/Transports.h" -ScriptMapMapName sQuestEndScripts; -ScriptMapMapName sQuestStartScripts; -ScriptMapMapName sSpellScripts; -ScriptMapMapName sGameObjectScripts; -ScriptMapMapName sGameObjectTemplateScripts; -ScriptMapMapName sEventScripts; -ScriptMapMapName sGossipScripts; -ScriptMapMapName sCreatureDeathScripts; -ScriptMapMapName sCreatureMovementScripts; -ScriptMapMapName sRelayScripts; +#include INSTANTIATE_SINGLETON_1(ScriptMgr); +constexpr std::array scriptTableNames +{ + "dbscripts_on_quest_end", + "dbscripts_on_quest_start", + "dbscripts_on_spell", + "dbscripts_on_go_use", + "dbscripts_on_go_template_use", + "dbscripts_on_event", + "dbscripts_on_gossip", + "dbscripts_on_creature_death", + "dbscripts_on_creature_movement", + "dbscripts_on_relay", + "internal_use", +}; + ScriptMgr::ScriptMgr() { - m_scheduledScripts = 0; } // ///////////////////////////////////////////////////////// @@ -99,16 +104,17 @@ bool ScriptMgr::CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEf return true; } -void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename) +void ScriptMgr::LoadScripts(ScriptMapType scriptType) { - if (IsScriptScheduled()) // function don't must be called in time scripts use. - return; + ScriptMapMapName scripts; + + const char* tablename = scriptTableNames[scriptType].data(); scripts.first = tablename; scripts.second.clear(); // need for reload support - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - QueryResult* result = WorldDatabase.PQuery("SELECT id, delay, command, datalong, datalong2, datalong3, buddy_entry, search_radius, data_flags, dataint, dataint2, dataint3, dataint4, datafloat, x, y, z, o, speed, condition_id FROM %s ORDER BY priority", tablename); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + std::unique_ptr result(WorldDatabase.PQuery("SELECT id, delay, command, datalong, datalong2, datalong3, buddy_entry, search_radius, data_flags, dataint, dataint2, dataint3, dataint4, datafloat, x, y, z, o, speed, condition_id FROM %s ORDER BY priority", tablename)); uint32 count = 0; @@ -751,11 +757,12 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename) } case SCRIPT_COMMAND_START_RELAY_SCRIPT: // 45 { - if (strcmp(scripts.first, "dbscripts_on_relay") != 0) // Relay scripts are done first and checked after load + if (scriptType != SCRIPT_TYPE_RELAY) // Relay scripts are done first and checked after load { if (tmp.relayScript.relayId) { - if (sRelayScripts.second.find(tmp.relayScript.relayId) == sRelayScripts.second.end()) + auto relayScript = GetScriptMap(SCRIPT_TYPE_RELAY); + if (relayScript->second.find(tmp.relayScript.relayId) == relayScript->second.end()) { sLog.outErrorDb("Table `dbscripts_on_relay` uses nonexistent relay ID %u in SCRIPT_COMMAND_START_RELAY_SCRIPT for script id %u.", tmp.relayScript.relayId, tmp.id); continue; @@ -923,182 +930,190 @@ void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename) ScriptMap emptyMap; scripts.second[tmp.id] = emptyMap; } - scripts.second[tmp.id].emplace(tmp.delay, tmp); + scripts.second[tmp.id].emplace(tmp.delay, std::make_shared(tmp)); ++count; } while (result->NextRow()); - delete result; + m_scriptMaps[scriptType] = std::make_shared(scripts); sLog.outString(">> Loaded %u script definitions from table %s", count, tablename); sLog.outString(); } -void ScriptMgr::LoadGameObjectScripts() -{ - LoadScripts(sGameObjectScripts, "dbscripts_on_go_use"); - - // check ids - for (ScriptMapMap::const_iterator itr = sGameObjectScripts.second.begin(); itr != sGameObjectScripts.second.end(); ++itr) - { - if (!sObjectMgr.GetGOData(itr->first)) - sLog.outErrorDb("Table `dbscripts_on_go_use` has not existing gameobject (GUID: %u) as script id", itr->first); - } -} - -void ScriptMgr::LoadGameObjectTemplateScripts() -{ - LoadScripts(sGameObjectTemplateScripts, "dbscripts_on_go_template_use"); - - // check ids - for (ScriptMapMap::const_iterator itr = sGameObjectTemplateScripts.second.begin(); itr != sGameObjectTemplateScripts.second.end(); ++itr) - { - if (!sObjectMgr.GetGameObjectInfo(itr->first)) - sLog.outErrorDb("Table `dbscripts_on_go_template_use` has not existing gameobject (Entry: %u) as script id", itr->first); - } -} - -void ScriptMgr::LoadQuestEndScripts() +void ScriptMgr::LoadScriptMap(ScriptMapType scriptType, bool reload) { - LoadScripts(sQuestEndScripts, "dbscripts_on_quest_end"); + LoadScripts(scriptType); - // check ids - for (ScriptMapMap::const_iterator itr = sQuestEndScripts.second.begin(); itr != sQuestEndScripts.second.end(); ++itr) + switch (scriptType) { - if (!sObjectMgr.GetQuestTemplate(itr->first)) - sLog.outErrorDb("Table `dbscripts_on_quest_end` has not existing quest (Id: %u) as script id", itr->first); - } -} - -void ScriptMgr::LoadQuestStartScripts() -{ - LoadScripts(sQuestStartScripts, "dbscripts_on_quest_start"); - - // check ids - for (ScriptMapMap::const_iterator itr = sQuestStartScripts.second.begin(); itr != sQuestStartScripts.second.end(); ++itr) - { - if (!sObjectMgr.GetQuestTemplate(itr->first)) - sLog.outErrorDb("Table `dbscripts_on_quest_start` has not existing quest (Id: %u) as script id", itr->first); - } -} - -void ScriptMgr::LoadSpellScripts() -{ - LoadScripts(sSpellScripts, "dbscripts_on_spell"); - - // check ids - for (ScriptMapMap::const_iterator itr = sSpellScripts.second.begin(); itr != sSpellScripts.second.end(); ++itr) - { - SpellEntry const* spellInfo = sSpellTemplate.LookupEntry(itr->first); - if (!spellInfo) + case SCRIPT_TYPE_QUEST_END: { - sLog.outErrorDb("Table `dbscripts_on_spell` has not existing spell (Id: %u) as script id", itr->first); - continue; + auto questEndScripts = GetScriptMap(scriptType); + // check ids + for (ScriptMapMap::const_iterator itr = questEndScripts->second.begin(); itr != questEndScripts->second.end(); ++itr) + { + if (!sObjectMgr.GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `dbscripts_on_quest_end` has not existing quest (Id: %u) as script id", itr->first); + } + break; } - - // check for correct spellEffect - bool found = false; - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + case SCRIPT_TYPE_QUEST_START: { - if (GetSpellStartDBScriptPriority(spellInfo, SpellEffectIndex(i))) + auto questStartScripts = GetScriptMap(scriptType); + // check ids + for (ScriptMapMap::const_iterator itr = questStartScripts->second.begin(); itr != questStartScripts->second.end(); ++itr) { - found = true; - break; + if (!sObjectMgr.GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `dbscripts_on_quest_start` has not existing quest (Id: %u) as script id", itr->first); } + break; } + case SCRIPT_TYPE_SPELL: + { + auto spellScripts = GetScriptMap(scriptType); + // check ids + for (ScriptMapMap::const_iterator itr = spellScripts->second.begin(); itr != spellScripts->second.end(); ++itr) + { + SpellEntry const* spellInfo = sSpellTemplate.LookupEntry(itr->first); + if (!spellInfo) + { + sLog.outErrorDb("Table `dbscripts_on_spell` has not existing spell (Id: %u) as script id", itr->first); + continue; + } - if (!found) - sLog.outErrorDb("Table `dbscripts_on_spell` has unsupported spell (Id: %u)", itr->first); - } -} - -void ScriptMgr::LoadEventScripts() -{ - LoadScripts(sEventScripts, "dbscripts_on_event"); - - std::set eventIds; // Store possible event ids - CollectPossibleEventIds(eventIds); - - // Then check if all scripts are in above list of possible script entries - for (ScriptMapMap::const_iterator itr = sEventScripts.second.begin(); itr != sEventScripts.second.end(); ++itr) - { - std::set::const_iterator itr2 = eventIds.find(itr->first); - if (itr2 == eventIds.end()) - sLog.outErrorDb("Table `dbscripts_on_event` has script (Id: %u) not referring to any fitting gameobject_template or any spell effect %u or path taxi node data", - itr->first, SPELL_EFFECT_SEND_EVENT); - } -} - -void ScriptMgr::LoadGossipScripts() -{ - LoadScripts(sGossipScripts, "dbscripts_on_gossip"); - - // checks are done in LoadGossipMenuItems and LoadGossipMenu -} - -void ScriptMgr::LoadCreatureMovementScripts() -{ - LoadScripts(sCreatureMovementScripts, "dbscripts_on_creature_movement"); - - // checks are done in WaypointManager::Load -} - -void ScriptMgr::LoadCreatureDeathScripts() -{ - LoadScripts(sCreatureDeathScripts, "dbscripts_on_creature_death"); + // check for correct spellEffect + bool found = false; + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (GetSpellStartDBScriptPriority(spellInfo, SpellEffectIndex(i))) + { + found = true; + break; + } + } - // check ids - for (ScriptMapMap::const_iterator itr = sCreatureDeathScripts.second.begin(); itr != sCreatureDeathScripts.second.end(); ++itr) - { - if (!sObjectMgr.GetCreatureTemplate(itr->first)) - sLog.outErrorDb("Table `dbscripts_on_creature_death` has not existing creature (Entry: %u) as script id", itr->first); - } -} + if (!found) + sLog.outErrorDb("Table `dbscripts_on_spell` has unsupported spell (Id: %u)", itr->first); + } + break; + } + case SCRIPT_TYPE_GAMEOBJECT: + { + auto goScripts = GetScriptMap(scriptType); + // check ids + for (ScriptMapMap::const_iterator itr = goScripts->second.begin(); itr != goScripts->second.end(); ++itr) + { + if (!sObjectMgr.GetGOData(itr->first)) + sLog.outErrorDb("Table `dbscripts_on_go_use` has not existing gameobject (GUID: %u) as script id", itr->first); + } + break; + } + case SCRIPT_TYPE_GAMEOBJECT_TEMPLATE: + { + auto goTemplateScripts = GetScriptMap(scriptType); + // check ids + for (ScriptMapMap::const_iterator itr = goTemplateScripts->second.begin(); itr != goTemplateScripts->second.end(); ++itr) + { + if (!sObjectMgr.GetGameObjectInfo(itr->first)) + sLog.outErrorDb("Table `dbscripts_on_go_template_use` has not existing gameobject (Entry: %u) as script id", itr->first); + } + break; + } + case SCRIPT_TYPE_EVENT: + { + std::set eventIds; // Store possible event ids + CollectPossibleEventIds(eventIds); -void ScriptMgr::LoadRelayScripts() -{ - LoadScripts(sRelayScripts, "dbscripts_on_relay"); + auto eventScripts = GetScriptMap(scriptType); - // check ids - for (ScriptMapMap::const_iterator itr = sRelayScripts.second.begin(); itr != sRelayScripts.second.end(); ++itr) - { - for (auto& data : itr->second) // need to check after load is complete, because of nesting + // Then check if all scripts are in above list of possible script entries + for (ScriptMapMap::const_iterator itr = eventScripts->second.begin(); itr != eventScripts->second.end(); ++itr) + { + std::set::const_iterator itr2 = eventIds.find(itr->first); + if (itr2 == eventIds.end()) + sLog.outErrorDb("Table `dbscripts_on_event` has script (Id: %u) not referring to any fitting gameobject_template or any spell effect %u or path taxi node data", + itr->first, SPELL_EFFECT_SEND_EVENT); + } + break; + } + case SCRIPT_TYPE_GOSSIP: { - if (data.second.command == SCRIPT_COMMAND_START_RELAY_SCRIPT) + break; + } + case SCRIPT_TYPE_CREATURE_DEATH: + { + // check ids + auto deathScripts = GetScriptMap(scriptType); + for (ScriptMapMap::const_iterator itr = deathScripts->second.begin(); itr != deathScripts->second.end(); ++itr) { - bool hasErrored = false; - if (data.second.relayScript.relayId) + if (!sObjectMgr.GetCreatureTemplate(itr->first)) + sLog.outErrorDb("Table `dbscripts_on_creature_death` has not existing creature (Entry: %u) as script id", itr->first); + } + break; + } + case SCRIPT_TYPE_CREATURE_MOVEMENT: + { + break; + } + case SCRIPT_TYPE_RELAY: + { + // check ids + auto relayScripts = GetScriptMap(scriptType); + for (ScriptMapMap::const_iterator itr = relayScripts->second.begin(); itr != relayScripts->second.end(); ++itr) + { + for (auto& data : itr->second) // need to check after load is complete, because of nesting { - if (sRelayScripts.second.find(data.second.relayScript.relayId) == sRelayScripts.second.end()) + if (data.second->command == SCRIPT_COMMAND_START_RELAY_SCRIPT) { - sLog.outErrorDb("Table `dbscripts_on_relay` uses nonexistent relay ID %u in SCRIPT_COMMAND_START_RELAY_SCRIPT for script id %u.", data.second.relayScript.relayId, data.second.id); - hasErrored = true; + bool hasErrored = false; + if (data.second->relayScript.relayId) + { + if (relayScripts->second.find(data.second->relayScript.relayId) == relayScripts->second.end()) + { + sLog.outErrorDb("Table `dbscripts_on_relay` uses nonexistent relay ID %u in SCRIPT_COMMAND_START_RELAY_SCRIPT for script id %u.", data.second->relayScript.relayId, data.second->id); + hasErrored = true; + } + } + + if (hasErrored) + continue; } } - - if (hasErrored) - continue; } + + // String templates are checked on string loading + CheckRandomRelayTemplates(); + break; } } - // String templates are checked on string loading - CheckRandomRelayTemplates(); + if (reload) + { + auto scriptMap = GetScriptMap(scriptType); + sMapMgr.DoForAllMaps([scriptType, scriptMap](Map* map) + { + map->GetMessager().AddMessage([scriptType, scriptMap](Map* map) + { + map->GetMapDataContainer().SetScriptMap(scriptType, scriptMap); + }); + }); + } } void ScriptMgr::LoadDbScriptStrings() { - CheckScriptTexts(sQuestEndScripts); - CheckScriptTexts(sQuestStartScripts); - CheckScriptTexts(sSpellScripts); - CheckScriptTexts(sGameObjectScripts); - CheckScriptTexts(sGameObjectTemplateScripts); - CheckScriptTexts(sEventScripts); - CheckScriptTexts(sGossipScripts); - CheckScriptTexts(sCreatureDeathScripts); - CheckScriptTexts(sCreatureMovementScripts); - CheckScriptTexts(sRelayScripts); + CheckScriptTexts(SCRIPT_TYPE_QUEST_END); + CheckScriptTexts(SCRIPT_TYPE_QUEST_START); + CheckScriptTexts(SCRIPT_TYPE_SPELL); + CheckScriptTexts(SCRIPT_TYPE_GAMEOBJECT); + CheckScriptTexts(SCRIPT_TYPE_GAMEOBJECT_TEMPLATE); + CheckScriptTexts(SCRIPT_TYPE_EVENT); + CheckScriptTexts(SCRIPT_TYPE_GOSSIP); + CheckScriptTexts(SCRIPT_TYPE_CREATURE_DEATH); + CheckScriptTexts(SCRIPT_TYPE_CREATURE_MOVEMENT); + CheckScriptTexts(SCRIPT_TYPE_RELAY); } void ScriptMgr::LoadDbScriptRandomTemplates() @@ -1142,33 +1157,35 @@ void ScriptMgr::CheckRandomStringTemplates(std::set& ids) void ScriptMgr::CheckRandomRelayTemplates() { + auto relayScripts = GetScriptMap(SCRIPT_TYPE_RELAY); for (auto& templateData : m_scriptTemplates[RELAY_TEMPLATE]) for (auto& data : templateData.second) - if (data.first && sRelayScripts.second.find(data.first) == sRelayScripts.second.end()) + if (data.first && relayScripts->second.find(data.first) == relayScripts->second.end()) sLog.outErrorDb("Table `dbscript_random_templates` entry (%u) uses nonexistent relay ID (%u).", templateData.first, data.first); } -void ScriptMgr::CheckScriptTexts(ScriptMapMapName const& scripts) +void ScriptMgr::CheckScriptTexts(ScriptMapType scriptType) { + ScriptMapMapName const& scripts = *GetScriptMap(scriptType).get(); for (ScriptMapMap::const_iterator itrMM = scripts.second.begin(); itrMM != scripts.second.end(); ++itrMM) { for (ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM) { - if (itrM->second.command == SCRIPT_COMMAND_TALK) + if (itrM->second->command == SCRIPT_COMMAND_TALK) { - for (int i : itrM->second.textId) + for (int i : itrM->second->textId) { if (i && !sObjectMgr.GetBroadcastText(i)) sLog.outErrorDb("Table `broadcast_text` is missing string id %u, used in database script table %s id %u.", i, scripts.first, itrMM->first); } - if (itrM->second.talk.stringTemplateId) + if (itrM->second->talk.stringTemplateId) { - auto& vector = m_scriptTemplates[STRING_TEMPLATE][itrM->second.talk.stringTemplateId]; + auto& vector = m_scriptTemplates[STRING_TEMPLATE][itrM->second->talk.stringTemplateId]; for (auto& data : vector) { if (!sObjectMgr.GetBroadcastText(data.first)) - sLog.outErrorDb("Table `broadcast_text` is missing string id %d, used in database script template table dbscript_random_templates id %u.", data.first, itrM->second.talk.stringTemplateId); + sLog.outErrorDb("Table `broadcast_text` is missing string id %d, used in database script template table dbscript_random_templates id %u.", data.first, itrM->second->talk.stringTemplateId); } } } @@ -1525,6 +1542,12 @@ Player* ScriptAction::GetPlayerTargetOrSourceAndLog(WorldObject* pSource, WorldO return pTarget && pTarget->GetTypeId() == TYPEID_PLAYER ? (Player*)pTarget : (Player*)pSource; } +ScriptAction::ScriptAction(ScriptMapType scriptType, Map* _map, ObjectGuid _sourceGuid, ObjectGuid _targetGuid, ObjectGuid _ownerGuid, std::shared_ptr _script) + : m_scriptType(scriptType), m_table(scriptTableNames[scriptType].data()), m_map(_map), m_sourceGuid(_sourceGuid), m_targetGuid(_targetGuid), m_ownerGuid(_ownerGuid), m_script(_script) +{ + +} + /// Handle one Script Step // Return true if and only if further parts of this script shall be skipped bool ScriptAction::HandleScriptStep() @@ -2737,7 +2760,7 @@ bool ScriptAction::ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTa chosenId = m_script->relayScript.relayId; if (chosenId) - m_map->ScriptsStart(sRelayScripts, chosenId, pSource, pTarget); + m_map->ScriptsStart(SCRIPT_TYPE_RELAY, chosenId, pSource, pTarget); break; } case SCRIPT_COMMAND_CAST_CUSTOM_SPELL: // 46 @@ -3185,6 +3208,11 @@ void ScriptMgr::CollectPossibleEventIds(std::set& eventIds) } } +std::shared_ptr ScriptMgr::GetScriptMap(ScriptMapType scriptMapType) +{ + return m_scriptMaps[scriptMapType]; +} + // Starters for events bool StartEvents_Event(Map* map, uint32 id, Object* source, Object* target, bool isStart/*=true*/) { @@ -3223,5 +3251,5 @@ bool StartEvents_Event(Map* map, uint32 id, Object* source, Object* target, bool else if (target && target->isType(TYPEMASK_CREATURE_OR_GAMEOBJECT)) execParam = Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET; - return map->ScriptsStart(sEventScripts, id, source, target, execParam); + return map->ScriptsStart(SCRIPT_TYPE_EVENT, id, source, target, execParam); } diff --git a/src/game/DBScripts/ScriptMgr.h b/src/game/DBScripts/ScriptMgr.h index c9476eb9d1..5a0f72ef26 100644 --- a/src/game/DBScripts/ScriptMgr.h +++ b/src/game/DBScripts/ScriptMgr.h @@ -584,12 +584,26 @@ struct ScriptInfo } }; +enum ScriptMapType +{ + SCRIPT_TYPE_QUEST_END = 0, + SCRIPT_TYPE_QUEST_START = 1, + SCRIPT_TYPE_SPELL = 2, + SCRIPT_TYPE_GAMEOBJECT = 3, + SCRIPT_TYPE_GAMEOBJECT_TEMPLATE = 4, + SCRIPT_TYPE_EVENT = 5, + SCRIPT_TYPE_GOSSIP = 6, + SCRIPT_TYPE_CREATURE_DEATH = 7, + SCRIPT_TYPE_CREATURE_MOVEMENT = 8, + SCRIPT_TYPE_RELAY = 9, + SCRIPT_TYPE_INTERNAL = 10, // must be last + SCRIPT_TYPE_MAX +}; + class ScriptAction { public: - ScriptAction(const char* _table, Map* _map, ObjectGuid _sourceGuid, ObjectGuid _targetGuid, ObjectGuid _ownerGuid, ScriptInfo const* _script) : - m_table(_table), m_map(_map), m_sourceGuid(_sourceGuid), m_targetGuid(_targetGuid), m_ownerGuid(_ownerGuid), m_script(_script) - {} + ScriptAction(ScriptMapType scriptType, Map* _map, ObjectGuid _sourceGuid, ObjectGuid _targetGuid, ObjectGuid _ownerGuid, std::shared_ptr _script); bool HandleScriptStep(); // return true IF AND ONLY IF the script should be terminated bool ExecuteDbscriptCommand(WorldObject* pSource, WorldObject* pTarget, Object* pSourceOrItem); @@ -609,12 +623,13 @@ class ScriptAction } private: + ScriptMapType m_scriptType; const char* m_table; // of which table the script was started Map* m_map; // Map on which the action will be executed ObjectGuid m_sourceGuid; ObjectGuid m_targetGuid; ObjectGuid m_ownerGuid; // owner of source if source is item - ScriptInfo const* m_script; // pointer to static script data + std::shared_ptr m_script; // pointer to script data // Helper functions bool GetScriptCommandObject(const ObjectGuid guid, bool includeItem, Object*& resultObject) const; @@ -626,21 +641,10 @@ class ScriptAction Player* GetPlayerTargetOrSourceAndLog(WorldObject* pSource, WorldObject* pTarget) const; }; -typedef std::multimap < uint32 /*delay*/, ScriptInfo > ScriptMap; +typedef std::multimap < uint32 /*delay*/, std::shared_ptr> ScriptMap; typedef std::map < uint32 /*id*/, ScriptMap > ScriptMapMap; typedef std::pair ScriptMapMapName; -extern ScriptMapMapName sQuestEndScripts; -extern ScriptMapMapName sQuestStartScripts; -extern ScriptMapMapName sSpellScripts; -extern ScriptMapMapName sGameObjectScripts; -extern ScriptMapMapName sGameObjectTemplateScripts; -extern ScriptMapMapName sEventScripts; -extern ScriptMapMapName sGossipScripts; -extern ScriptMapMapName sCreatureDeathScripts; -extern ScriptMapMapName sCreatureMovementScripts; -extern ScriptMapMapName sRelayScripts; - class ScriptMgr { enum RandomTemplates @@ -654,16 +658,7 @@ class ScriptMgr ScriptMgr(); ~ScriptMgr() {}; - void LoadGameObjectScripts(); - void LoadGameObjectTemplateScripts(); - void LoadQuestEndScripts(); - void LoadQuestStartScripts(); - void LoadEventScripts(); - void LoadSpellScripts(); - void LoadGossipScripts(); - void LoadCreatureDeathScripts(); - void LoadCreatureMovementScripts(); - void LoadRelayScripts(); + void LoadScriptMap(ScriptMapType scriptType, bool reload = false); void LoadDbScriptStrings(); void LoadDbScriptRandomTemplates(); @@ -680,16 +675,13 @@ class ScriptMgr int32 GetRandomScriptStringFromTemplate(uint32 id); int32 GetRandomRelayDbscriptFromTemplate(uint32 id); - uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; } - uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; } - uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); } - bool IsScriptScheduled() const { return m_scheduledScripts > 0; } static bool CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEffectIndex effIdx); static void CollectPossibleEventIds(std::set& eventIds); + std::shared_ptr GetScriptMap(ScriptMapType scriptMapType); private: - void LoadScripts(ScriptMapMapName& scripts, const char* tablename); - void CheckScriptTexts(ScriptMapMapName const& scripts); + void LoadScripts(ScriptMapType scriptType); + void CheckScriptTexts(ScriptMapType scriptType); typedef std::vector ScriptNameMap; typedef std::unordered_map AreaTriggerScriptMap; @@ -704,8 +696,7 @@ class ScriptMgr ScriptTemplateMap m_scriptTemplatesExplicitlyChanced[MAX_TYPE]; ScriptNameMap m_scriptNames; - // atomic op counter for active scripts amount - std::atomic_long m_scheduledScripts; + std::shared_ptr m_scriptMaps[SCRIPT_TYPE_MAX]; }; // Starters for events diff --git a/src/game/Entities/Creature.cpp b/src/game/Entities/Creature.cpp index 1cfcab33ac..04c2502947 100644 --- a/src/game/Entities/Creature.cpp +++ b/src/game/Entities/Creature.cpp @@ -1708,7 +1708,7 @@ bool Creature::LoadFromDB(uint32 dbGuid, Map* map, uint32 newGuid, uint32 forced AIM_Initialize(); if (data && data->spawnTemplate->relayId) - GetMap()->ScriptsStart(sRelayScripts, data->spawnTemplate->relayId, this, nullptr); + GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, data->spawnTemplate->relayId, this, nullptr); // Creature Linking, Initial load is handled like respawn if (m_isCreatureLinkingTrigger && IsAlive()) diff --git a/src/game/Entities/GameObject.cpp b/src/game/Entities/GameObject.cpp index 37b1fc2030..2d7de18bc1 100644 --- a/src/game/Entities/GameObject.cpp +++ b/src/game/Entities/GameObject.cpp @@ -1398,7 +1398,7 @@ void GameObject::Use(Unit* user, SpellEntry const* spellInfo) bool scriptReturnValue = user->GetTypeId() == TYPEID_PLAYER && sScriptDevAIMgr.OnGameObjectUse((Player*)user, this); if (!scriptReturnValue) - GetMap()->ScriptsStart(sGameObjectTemplateScripts, GetEntry(), spellCaster, this); + GetMap()->ScriptsStart(SCRIPT_TYPE_GAMEOBJECT_TEMPLATE, GetEntry(), spellCaster, this); if (AI()) AI()->OnUse(user, spellInfo); @@ -1414,7 +1414,7 @@ void GameObject::Use(Unit* user, SpellEntry const* spellInfo) // activate script if (!scriptReturnValue) - GetMap()->ScriptsStart(sGameObjectScripts, GetDbGuid(), spellCaster, this); + GetMap()->ScriptsStart(SCRIPT_TYPE_GAMEOBJECT, GetDbGuid(), spellCaster, this); return; } case GAMEOBJECT_TYPE_BUTTON: // 1 @@ -1437,7 +1437,7 @@ void GameObject::Use(Unit* user, SpellEntry const* spellInfo) // activate script if (!scriptReturnValue) - GetMap()->ScriptsStart(sGameObjectScripts, GetDbGuid(), spellCaster, this); + GetMap()->ScriptsStart(SCRIPT_TYPE_GAMEOBJECT, GetDbGuid(), spellCaster, this); return; } @@ -1614,7 +1614,7 @@ void GameObject::Use(Unit* user, SpellEntry const* spellInfo) // activate script if (!scriptReturnValue) - GetMap()->ScriptsStart(sGameObjectScripts, GetDbGuid(), spellCaster, this); + GetMap()->ScriptsStart(SCRIPT_TYPE_GAMEOBJECT, GetDbGuid(), spellCaster, this); else return; diff --git a/src/game/Entities/Object.cpp b/src/game/Entities/Object.cpp index fb4b5bef33..8e9c69c13d 100644 --- a/src/game/Entities/Object.cpp +++ b/src/game/Entities/Object.cpp @@ -2142,7 +2142,7 @@ Creature* WorldObject::SummonCreature(TempSpawnSettings settings, Map* map) creature->Summon(settings.spawnType, settings.despawnTime); // Also initializes the AI and MMGen if (relayId) - map->ScriptsStart(sRelayScripts, relayId, creature, settings.dbscriptTarget); + map->ScriptsStart(SCRIPT_TYPE_RELAY, relayId, creature, settings.dbscriptTarget); if (settings.corpseDespawnTime) creature->SetCorpseDelay(settings.corpseDespawnTime); diff --git a/src/game/Entities/Player.cpp b/src/game/Entities/Player.cpp index 189304cfa0..7c57ff6ff0 100644 --- a/src/game/Entities/Player.cpp +++ b/src/game/Entities/Player.cpp @@ -12595,9 +12595,9 @@ void Player::OnGossipSelect(WorldObject* pSource, uint32 gossipListId, uint32 me if (pMenuData && menuData.m_gAction_script) { if (pSource->GetTypeId() == TYPEID_UNIT) - GetMap()->ScriptsStart(sGossipScripts, menuData.m_gAction_script, pSource, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); + GetMap()->ScriptsStart(SCRIPT_TYPE_GOSSIP, menuData.m_gAction_script, pSource, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT) - GetMap()->ScriptsStart(sGossipScripts, menuData.m_gAction_script, this, pSource, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET); + GetMap()->ScriptsStart(SCRIPT_TYPE_GOSSIP, menuData.m_gAction_script, this, pSource, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET); } } @@ -12639,7 +12639,7 @@ uint32 Player::GetGossipTextId(uint32 menuId, WorldObject* pSource) // Start related script if (scriptId) - GetMap()->ScriptsStart(sGossipScripts, scriptId, this, pSource, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET); + GetMap()->ScriptsStart(SCRIPT_TYPE_GOSSIP, scriptId, this, pSource, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET); return textId; } @@ -13170,7 +13170,7 @@ void Player::AddQuest(Quest const* pQuest, Object* questGiver) // starting initial DB quest script if (pQuest->GetQuestStartScript() != 0) - GetMap()->ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); + GetMap()->ScriptsStart(SCRIPT_TYPE_QUEST_START, pQuest->GetQuestStartScript(), questGiver, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); } // remove start item if not need @@ -13370,7 +13370,7 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, } if (!handled && pQuest->GetQuestCompleteScript() != 0) - GetMap()->ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); + GetMap()->ScriptsStart(SCRIPT_TYPE_QUEST_END, pQuest->GetQuestCompleteScript(), questGiver, this, Map::SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE); // Find spell cast on spell reward if any, then find the appropriate caster and cast it uint32 spellId = pQuest->GetRewSpellCast(); diff --git a/src/game/Entities/Unit.cpp b/src/game/Entities/Unit.cpp index 122032c26a..66dd48a83e 100644 --- a/src/game/Entities/Unit.cpp +++ b/src/game/Entities/Unit.cpp @@ -1422,7 +1422,7 @@ void Unit::JustKilledCreature(Unit* killer, Creature* victim, Player* responsibl outdoorPvP->HandleCreatureDeath(victim); // Start creature death script - victim->GetMap()->ScriptsStart(sCreatureDeathScripts, victim->GetEntry(), victim, responsiblePlayer ? responsiblePlayer : killer); + victim->GetMap()->ScriptsStart(SCRIPT_TYPE_CREATURE_DEATH, victim->GetEntry(), victim, responsiblePlayer ? responsiblePlayer : killer); if (victim->IsLinkingEventTrigger()) victim->GetMap()->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_DIE, victim); diff --git a/src/game/Globals/ObjectMgr.cpp b/src/game/Globals/ObjectMgr.cpp index 3612ea1e66..1d23320581 100644 --- a/src/game/Globals/ObjectMgr.cpp +++ b/src/game/Globals/ObjectMgr.cpp @@ -9459,10 +9459,8 @@ void ObjectMgr::LoadNpcGossips() void ObjectMgr::LoadGossipMenu(std::set& gossipScriptSet) { m_mGossipMenusMap.clear(); - // 0 1 2 - QueryResult* result = WorldDatabase.Query("SELECT entry, text_id, script_id, " - // 3 - "condition_id FROM gossip_menu"); + // 0 1 2 3 + std::unique_ptr result(WorldDatabase.Query("SELECT entry, text_id, script_id, condition_id FROM gossip_menu")); if (!result) { @@ -9473,6 +9471,8 @@ void ObjectMgr::LoadGossipMenu(std::set& gossipScriptSet) return; } + auto gossipScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_GOSSIP); + BarGoLink bar(result->GetRowCount()); uint32 count = 0; @@ -9500,7 +9500,7 @@ void ObjectMgr::LoadGossipMenu(std::set& gossipScriptSet) // Check script-id if (gMenu.script_id) { - if (sGossipScripts.second.find(gMenu.script_id) == sGossipScripts.second.end()) + if (gossipScripts->second.find(gMenu.script_id) == gossipScripts->second.end()) { sLog.outErrorDb("Table gossip_menu for menu %u, text-id %u have script_id %u that does not exist in `dbscripts_on_gossip`, ignoring", gMenu.entry, gMenu.text_id, gMenu.script_id); continue; @@ -9526,8 +9526,6 @@ void ObjectMgr::LoadGossipMenu(std::set& gossipScriptSet) } while (result->NextRow()); - delete result; - // post loading tests for (uint32 i = 1; i < sCreatureStorage.GetMaxEntry(); ++i) { @@ -9600,6 +9598,8 @@ void ObjectMgr::LoadGossipMenuItems(std::set& gossipScriptSet) menu_ids.erase(cInfo->GossipMenuId); } + auto gossipScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_GOSSIP); + do { bar.step(); @@ -9682,7 +9682,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set& gossipScriptSet) if (gMenuItem.action_script_id) { - if (sGossipScripts.second.find(gMenuItem.action_script_id) == sGossipScripts.second.end()) + if (gossipScripts->second.find(gMenuItem.action_script_id) == gossipScripts->second.end()) { sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `dbscripts_on_gossip`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id); continue; @@ -9722,9 +9722,10 @@ void ObjectMgr::LoadGossipMenuItems(std::set& gossipScriptSet) void ObjectMgr::LoadGossipMenus() { + auto gossipScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_GOSSIP); // Check which script-ids in dbscripts_on_gossip are not used std::set gossipScriptSet; - for (ScriptMapMap::const_iterator itr = sGossipScripts.second.begin(); itr != sGossipScripts.second.end(); ++itr) + for (ScriptMapMap::const_iterator itr = gossipScripts->second.begin(); itr != gossipScripts->second.end(); ++itr) gossipScriptSet.insert(itr->first); // Load gossip_menu and gossip_menu_option data @@ -9734,7 +9735,7 @@ void ObjectMgr::LoadGossipMenus() LoadGossipMenuItems(gossipScriptSet); for (uint32 itr : gossipScriptSet) - sLog.outErrorDb("Table `dbscripts_on_gossip` contains unused script, id %u.", itr); + sLog.outErrorDb("Table `dbscripts_on_gossip` contains unused script, id %u.", itr); } void ObjectMgr::LoadDungeonEncounters() diff --git a/src/game/Maps/Map.cpp b/src/game/Maps/Map.cpp index d86d88a9c7..a44439f6ca 100644 --- a/src/game/Maps/Map.cpp +++ b/src/game/Maps/Map.cpp @@ -48,9 +48,6 @@ Map::~Map() { UnloadAll(true); - if (!m_scriptSchedule.empty()) - sScriptMgr.DecreaseScheduledScriptCount(m_scriptSchedule.size()); - if (m_persistentState) m_persistentState->SetUsedByMapState(nullptr); // field pointer can be deleted after this @@ -1932,13 +1929,14 @@ bool Map::CanEnter(Player* player) } /// Put scripts in the execution queue -bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams /*=SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET*/) +bool Map::ScriptsStart(ScriptMapType scriptType, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams /*=SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET*/) { MANGOS_ASSERT(source); ///- Find the script map - ScriptMapMap::const_iterator scriptInfoMapMapItr = scripts.second.find(id); - if (scriptInfoMapMapItr == scripts.second.end()) + auto scriptMapMap = GetMapDataContainer().GetScriptMap(scriptType); + ScriptMapMap::const_iterator scriptInfoMapMapItr = scriptMapMap->second.find(id); + if (scriptInfoMapMapItr == scriptMapMap->second.end()) return false; // prepare static data @@ -1950,11 +1948,11 @@ bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* sourc { for (ScriptScheduleMap::const_iterator searchItr = m_scriptSchedule.begin(); searchItr != m_scriptSchedule.end(); ++searchItr) { - if (searchItr->second.IsSameScript(scripts.first, id, + if (searchItr->second.IsSameScript(scriptMapMap->first, id, execParams & SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE ? sourceGuid : ObjectGuid(), execParams & SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET ? targetGuid : ObjectGuid(), ownerGuid)) { - DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u. Skip script as script already started for source %s, target %s - ScriptsStartParams %u", scripts.first, id, sourceGuid.GetString().c_str(), targetGuid.GetString().c_str(), execParams); + DETAIL_FILTER_LOG(LOG_FILTER_DB_SCRIPT, "DB-SCRIPTS: Process table `%s` id %u. Skip script as script already started for source %s, target %s - ScriptsStartParams %u", scriptMapMap->first, id, sourceGuid.GetString().c_str(), targetGuid.GetString().c_str(), execParams); return true; } } @@ -1968,11 +1966,11 @@ bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* sourc while (scriptInfoItr != scriptMap.end()) { auto const& scriptInfo = scriptInfoItr->second; - if (scriptInfo.delay > 0) + if (scriptInfo->delay > 0) break; // fire script with 0 delay directly - ScriptAction sa(scripts.first, this, sourceGuid, targetGuid, ownerGuid, &scriptInfo); + ScriptAction sa(scriptType, this, sourceGuid, targetGuid, ownerGuid, scriptInfo); if (sa.HandleScriptStep()) return true; // script failed we should not continue further (command 31 or any error occured) @@ -1983,9 +1981,8 @@ bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* sourc for (; scriptInfoItr != scriptMap.end(); ++scriptInfoItr) { auto const& scriptInfo = scriptInfoItr->second; - ScriptAction sa(scripts.first, this, sourceGuid, targetGuid, ownerGuid, &scriptInfo); + ScriptAction sa(scriptType, this, sourceGuid, targetGuid, ownerGuid, scriptInfo); m_scriptSchedule.emplace(GetCurrentClockTime() + std::chrono::milliseconds(scriptInfoItr->first), sa); - sScriptMgr.IncreaseScheduledScriptsCount(); } return true; @@ -2000,12 +1997,11 @@ void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* sou ObjectGuid targetGuid = target ? target->GetObjectGuid() : ObjectGuid(); ObjectGuid ownerGuid = source->isType(TYPEMASK_ITEM) ? ((Item*)source)->GetOwnerGuid() : ObjectGuid(); - ScriptAction sa("Internal Activate Command used for spell", this, sourceGuid, targetGuid, ownerGuid, &script); + ScriptAction sa(SCRIPT_TYPE_INTERNAL, this, sourceGuid, targetGuid, ownerGuid, std::make_shared(script)); if (delay) { m_scriptSchedule.emplace(GetCurrentClockTime() + std::chrono::milliseconds(delay), sa); - sScriptMgr.IncreaseScheduledScriptsCount(); } else sa.HandleScriptStep(); @@ -2034,20 +2030,14 @@ void Map::ScriptsProcess() for (ScriptScheduleMap::iterator rmItr = m_scriptSchedule.begin(); rmItr != m_scriptSchedule.end();) { if (rmItr->second.IsSameScript(tableName, id, sourceGuid, targetGuid, ownerGuid)) - { m_scriptSchedule.erase(rmItr++); - sScriptMgr.DecreaseScheduledScriptCount(); - } else ++rmItr; } } else - { m_scriptSchedule.erase(iter); - sScriptMgr.DecreaseScheduledScriptCount(); - } iter = m_scriptSchedule.begin(); } } diff --git a/src/game/Maps/Map.h b/src/game/Maps/Map.h index a0846150e6..68dad56869 100644 --- a/src/game/Maps/Map.h +++ b/src/game/Maps/Map.h @@ -261,7 +261,7 @@ class Map : public GridRefManager SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET = 0x02, // Start Script only if not yet started (uniqueness identified by id and target) SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET = 0x03, // Start Script only if not yet started (uniqueness identified by id, source and target) }; - bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE); + bool ScriptsStart(ScriptMapType scriptType, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); // must called with AddToWorld diff --git a/src/game/Maps/MapDataContainer.cpp b/src/game/Maps/MapDataContainer.cpp index 360a4e897f..defedd2ef3 100644 --- a/src/game/Maps/MapDataContainer.cpp +++ b/src/game/Maps/MapDataContainer.cpp @@ -25,6 +25,8 @@ MapDataContainer::MapDataContainer() : m_spellListContainer(sObjectMgr.GetCreatu m_spawnGroupContainer(sObjectMgr.GetSpawnGroupContainer()), m_CreatureEventAIEventEntryMap(sEventAIMgr.GetCreatureEventEntryAIMap()), m_CreatureEventAIEventGuidMap(sEventAIMgr.GetCreatureEventGuidAIMap()), m_creatureEventAIComputedDataMap(sEventAIMgr.GetEAIComputedDataMap()) { + for (uint32 i = 0; i < SCRIPT_TYPE_MAX; ++i) + SetScriptMap(ScriptMapType(i), sScriptMgr.GetScriptMap(ScriptMapType(i))); } void MapDataContainer::SetCreatureSpellListContainer(std::shared_ptr container) @@ -85,3 +87,13 @@ std::shared_ptr MapDataContainer::GetEAIC { return m_creatureEventAIComputedDataMap; } + +void MapDataContainer::SetScriptMap(ScriptMapType scriptMapType, std::shared_ptr scriptMap) +{ + m_scriptMaps[scriptMapType] = scriptMap; +} + +std::shared_ptr MapDataContainer::GetScriptMap(ScriptMapType scriptMapType) +{ + return m_scriptMaps[scriptMapType]; +} diff --git a/src/game/Maps/MapDataContainer.h b/src/game/Maps/MapDataContainer.h index 5686408045..5562b52aa2 100644 --- a/src/game/Maps/MapDataContainer.h +++ b/src/game/Maps/MapDataContainer.h @@ -50,6 +50,9 @@ class MapDataContainer std::shared_ptr GetCreatureEventEntryAIMap() const; std::shared_ptr GetCreatureEventGuidAIMap() const; std::shared_ptr GetEAIComputedDataMap() const; + + void SetScriptMap(ScriptMapType scriptMapType, std::shared_ptr scriptMap); + std::shared_ptr GetScriptMap(ScriptMapType scriptMapType); private: std::shared_ptr m_spellListContainer; std::shared_ptr m_spawnGroupContainer; @@ -57,6 +60,8 @@ class MapDataContainer std::shared_ptr m_CreatureEventAIEventEntryMap; std::shared_ptr m_CreatureEventAIEventGuidMap; std::shared_ptr m_creatureEventAIComputedDataMap; + + std::shared_ptr m_scriptMaps[SCRIPT_TYPE_MAX]; }; #endif \ No newline at end of file diff --git a/src/game/MotionGenerators/PathMovementGenerator.cpp b/src/game/MotionGenerators/PathMovementGenerator.cpp index 264f332073..baee2ace74 100644 --- a/src/game/MotionGenerators/PathMovementGenerator.cpp +++ b/src/game/MotionGenerators/PathMovementGenerator.cpp @@ -202,7 +202,7 @@ void AbstractPathMovementGenerator::MovementInform(Unit& unit) if (node.script_id) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", node.script_id, index, unit.GetGuidStr().c_str()); - unit.GetMap()->ScriptsStart(sCreatureMovementScripts, node.script_id, &unit, &unit); + unit.GetMap()->ScriptsStart(SCRIPT_TYPE_CREATURE_MOVEMENT, node.script_id, &unit, &unit); } // unit.SummonCreature(1, node.x, node.y, node.z, node.orientation, TEMPSPAWN_TIMED_DESPAWN, 5000); diff --git a/src/game/MotionGenerators/PointMovementGenerator.cpp b/src/game/MotionGenerators/PointMovementGenerator.cpp index 8aaa45d83f..f558946615 100644 --- a/src/game/MotionGenerators/PointMovementGenerator.cpp +++ b/src/game/MotionGenerators/PointMovementGenerator.cpp @@ -124,7 +124,7 @@ void PointMovementGenerator::MovementInform(Unit& unit) } if (m_relayId) - unit.GetMap()->ScriptsStart(sRelayScripts, m_relayId, &unit, m_guid ? unit.GetMap()->GetWorldObject(m_guid) : nullptr); + unit.GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, m_relayId, &unit, m_guid ? unit.GetMap()->GetWorldObject(m_guid) : nullptr); } void RetreatMovementGenerator::Initialize(Unit& unit) diff --git a/src/game/MotionGenerators/WaypointManager.cpp b/src/game/MotionGenerators/WaypointManager.cpp index dc790210ee..dc974c461a 100644 --- a/src/game/MotionGenerators/WaypointManager.cpp +++ b/src/game/MotionGenerators/WaypointManager.cpp @@ -46,8 +46,10 @@ char const* waypointKeyColumn[] = void CheckDbscript(WaypointNode& node, uint32 entry, uint32 point, std::set& movementScriptSet, std::string const& tablename) { - auto iter = sCreatureMovementScripts.second.find(node.script_id); - if (iter == sCreatureMovementScripts.second.end()) + auto creatureMovementScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_CREATURE_MOVEMENT); + auto relayScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_RELAY); + auto iter = creatureMovementScripts->second.find(node.script_id); + if (iter == creatureMovementScripts->second.end()) { sLog.outErrorDb("Table %s for entry %u, point %u have script_id %u that does not exist in `dbscripts_on_creature_movement`, ignoring", tablename.data(), entry, point, node.script_id); return; @@ -58,47 +60,48 @@ void CheckDbscript(WaypointNode& node, uint32 entry, uint32 point, std::setsecond.find(scriptInfo.relayScript.relayId); + if (iter == relayScripts->second.end()) { - if (item.second.relayScript.templateId) + if (scriptInfo.relayScript.templateId) { ScriptMgr::ScriptTemplateVector scriptTemplate; - sScriptMgr.GetScriptRelayTemplate(item.second.relayScript.templateId, scriptTemplate); + sScriptMgr.GetScriptRelayTemplate(scriptInfo.relayScript.templateId, scriptTemplate); for (auto& item : scriptTemplate) { - auto iter = sRelayScripts.second.find(item.first); - if (iter != sRelayScripts.second.end()) + auto iter = relayScripts->second.find(item.first); + if (iter != relayScripts->second.end()) { auto& data = *iter; for (auto& item : data.second) { - if (item.second.delay != 0) + if (scriptInfo.delay != 0) break; - if (item.second.command == SCRIPT_COMMAND_DESPAWN_SELF && item.second.delay == 0 && item.second.despawn.despawnDelay == 0) + if (scriptInfo.command == SCRIPT_COMMAND_DESPAWN_SELF && scriptInfo.delay == 0 && scriptInfo.despawn.despawnDelay == 0) { delay = true; sLog.outErrorDb("Table %s entry %u point %u has no delay and no delay despawn script. Adding delay to point.", tablename.data(), entry, point); break; } - else if (item.second.command == SCRIPT_COMMAND_MOVEMENT) + else if (scriptInfo.command == SCRIPT_COMMAND_MOVEMENT) { delay = true; sLog.outErrorDb("Table %s entry %u point %u has no delay but changes movegen. Adding delay to point.", tablename.data(), entry, point); @@ -118,15 +121,15 @@ void CheckDbscript(WaypointNode& node, uint32 entry, uint32 point, std::set movementScriptSet; - for (ScriptMapMap::const_iterator itr = sCreatureMovementScripts.second.begin(); itr != sCreatureMovementScripts.second.end(); ++itr) + auto creatureMovementScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_CREATURE_MOVEMENT); + for (ScriptMapMap::const_iterator itr = creatureMovementScripts->second.begin(); itr != creatureMovementScripts->second.end(); ++itr) movementScriptSet.insert(itr->first); // ///////////////////////////////////////////////////// @@ -735,5 +739,6 @@ bool WaypointManager::SetNodeScriptId(uint32 entry, uint32 dbGuid, uint32 point, if (find != path->end()) find->second.script_id = scriptId; - return sCreatureMovementScripts.second.find(scriptId) != sCreatureMovementScripts.second.end(); + auto creatureMovementScripts = sScriptMgr.GetScriptMap(SCRIPT_TYPE_CREATURE_MOVEMENT); + return creatureMovementScripts->second.find(scriptId) != creatureMovementScripts->second.end(); } diff --git a/src/game/MotionGenerators/WaypointMovementGenerator.cpp b/src/game/MotionGenerators/WaypointMovementGenerator.cpp index 564814d88e..041d4d5866 100644 --- a/src/game/MotionGenerators/WaypointMovementGenerator.cpp +++ b/src/game/MotionGenerators/WaypointMovementGenerator.cpp @@ -183,7 +183,7 @@ void WaypointMovementGenerator::OnArrived(Creature& creature) if (node.script_id) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", node.script_id, i_currentNode, creature.GetGuidStr().c_str()); - creature.GetMap()->ScriptsStart(sCreatureMovementScripts, node.script_id, &creature, m_guid ? creature.GetMap()->GetWorldObject(m_guid) : &creature); + creature.GetMap()->ScriptsStart(SCRIPT_TYPE_CREATURE_MOVEMENT, node.script_id, &creature, m_guid ? creature.GetMap()->GetWorldObject(m_guid) : &creature); } // Inform script diff --git a/src/game/MotionGenerators/WrapperMovementGenerator.cpp b/src/game/MotionGenerators/WrapperMovementGenerator.cpp index 6fffa4fd88..6235d8e47f 100644 --- a/src/game/MotionGenerators/WrapperMovementGenerator.cpp +++ b/src/game/MotionGenerators/WrapperMovementGenerator.cpp @@ -138,7 +138,7 @@ void AbstractWrapperMovementGenerator::Inform(Unit& owner) } if (m_relayId) - owner.GetMap()->ScriptsStart(sRelayScripts, m_relayId, &owner, m_guid ? owner.GetMap()->GetWorldObject(m_guid) : nullptr); + owner.GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, m_relayId, &owner, m_guid ? owner.GetMap()->GetWorldObject(m_guid) : nullptr); } void EffectMovementGenerator::Initialize(Unit& owner) diff --git a/src/game/Spells/SpellEffects.cpp b/src/game/Spells/SpellEffects.cpp index 36cabbae2d..bc152c72ab 100644 --- a/src/game/Spells/SpellEffects.cpp +++ b/src/game/Spells/SpellEffects.cpp @@ -3015,9 +3015,9 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectDummy", m_spellInfo->Id); if (effectTargetType == TARGET_TYPE_UNIT || effectTargetType == TARGET_TYPE_UNIT_DEST) - m_trueCaster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_trueCaster, unitTarget); + m_trueCaster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_trueCaster, unitTarget); else if (effectTargetType == TARGET_TYPE_GAMEOBJECT || (effectTargetType == TARGET_TYPE_LOCK && gameObjTarget)) - m_trueCaster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_trueCaster, gameObjTarget); + m_trueCaster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_trueCaster, gameObjTarget); } void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx) @@ -3034,7 +3034,7 @@ void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx) if (startDBScript) { DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectTriggerSpell", m_spellInfo->Id); - startDBScript = m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); + startDBScript = m_caster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_caster, unitTarget); } if (!startDBScript) @@ -3228,7 +3228,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffectIndex effect_idx) if (unitTarget) { DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectTriggerMissileSpell", m_spellInfo->Id); - m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); + m_caster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_caster, unitTarget); } else sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u", @@ -7339,9 +7339,9 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx) DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectScriptEffect", m_spellInfo->Id); if (effectTargetType == TARGET_TYPE_UNIT || effectTargetType == TARGET_TYPE_UNIT_DEST) - m_trueCaster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_trueCaster, unitTarget); + m_trueCaster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_trueCaster, unitTarget); else if (effectTargetType == TARGET_TYPE_GAMEOBJECT || (effectTargetType == TARGET_TYPE_LOCK && gameObjTarget)) - m_trueCaster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_trueCaster, gameObjTarget); + m_trueCaster->GetMap()->ScriptsStart(SCRIPT_TYPE_SPELL, m_spellInfo->Id, m_trueCaster, gameObjTarget); } void Spell::EffectSanctuary(SpellEffectIndex /*eff_idx*/) diff --git a/src/game/World/World.cpp b/src/game/World/World.cpp index fb5fc6a21a..9f20b23d61 100644 --- a/src/game/World/World.cpp +++ b/src/game/World/World.cpp @@ -1202,16 +1202,16 @@ void World::SetInitialWorldSettings() sScriptMgr.LoadDbScriptRandomTemplates(); ///- Load and initialize DBScripts Engine sLog.outString("Loading DB-Scripts Engine..."); - sScriptMgr.LoadRelayScripts(); // must be first in dbscripts loading - sScriptMgr.LoadGossipScripts(); // must be before gossip menu options - sScriptMgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate - sScriptMgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate - sScriptMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data) - sScriptMgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data) - sScriptMgr.LoadGameObjectTemplateScripts(); // must be after load Creature/Gameobject(Template/Data) - sScriptMgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data) - sScriptMgr.LoadCreatureDeathScripts(); // must be after load Creature/Gameobject(Template/Data) - sScriptMgr.LoadCreatureMovementScripts(); // before loading from creature_movement + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_RELAY); // must be first in dbscripts loading + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GOSSIP); // must be before gossip menu options + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_QUEST_START); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_QUEST_END); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_SPELL); // must be after load Creature/Gameobject(Template/Data) + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GAMEOBJECT); // must be after load Creature/Gameobject(Template/Data) + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_GAMEOBJECT_TEMPLATE); // must be after load Creature/Gameobject(Template/Data) + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_EVENT); // must be after load Creature/Gameobject(Template/Data) + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_CREATURE_DEATH); // must be after load Creature/Gameobject(Template/Data) + sScriptMgr.LoadScriptMap(SCRIPT_TYPE_CREATURE_MOVEMENT); // before loading from creature_movement sObjectMgr.LoadAreatriggerLocales(); sLog.outString(">>> Scripts loaded"); sLog.outString();