· 10 years ago · Sep 25, 2016, 03:04 AM
1/*
2 * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "ScriptMgr.h"
20#include "ScriptReloadMgr.h"
21#include "Config.h"
22#include "DatabaseEnv.h"
23#include "DBCStores.h"
24#include "ObjectMgr.h"
25#include "OutdoorPvPMgr.h"
26#include "ScriptSystem.h"
27#include "Transport.h"
28#include "Vehicle.h"
29#include "SmartAI.h"
30#include "SpellInfo.h"
31#include "SpellScript.h"
32#include "GossipDef.h"
33#include "CreatureAIImpl.h"
34#include "Player.h"
35#include "WorldPacket.h"
36#ifdef ELUNA
37#include "LuaEngine.h"
38#include "ElunaUtility.h"
39#endif
40#include "WorldSession.h"
41#include "Chat.h"
42#include "MapManager.h"
43#include "LFGScripts.h"
44#include "InstanceScript.h"
45
46// Trait which indicates whether this script type
47// must be assigned in the database.
48template<typename>
49struct is_script_database_bound
50 : std::false_type { };
51
52template<>
53struct is_script_database_bound<SpellScriptLoader>
54 : std::true_type { };
55
56template<>
57struct is_script_database_bound<InstanceMapScript>
58 : std::true_type { };
59
60template<>
61struct is_script_database_bound<ItemScript>
62 : std::true_type { };
63
64template<>
65struct is_script_database_bound<CreatureScript>
66 : std::true_type { };
67
68template<>
69struct is_script_database_bound<GameObjectScript>
70 : std::true_type { };
71
72template<>
73struct is_script_database_bound<VehicleScript>
74 : std::true_type { };
75
76template<>
77struct is_script_database_bound<AreaTriggerScript>
78 : std::true_type { };
79
80template<>
81struct is_script_database_bound<BattlegroundScript>
82 : std::true_type { };
83
84template<>
85struct is_script_database_bound<OutdoorPvPScript>
86 : std::true_type { };
87
88template<>
89struct is_script_database_bound<WeatherScript>
90 : std::true_type { };
91
92template<>
93struct is_script_database_bound<ConditionScript>
94 : std::true_type { };
95
96template<>
97struct is_script_database_bound<TransportScript>
98 : std::true_type { };
99
100template<>
101struct is_script_database_bound<AchievementCriteriaScript>
102 : std::true_type { };
103
104enum Spells
105{
106 SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084
107};
108
109class ScriptRegistryInterface
110{
111public:
112 ScriptRegistryInterface() { }
113 virtual ~ScriptRegistryInterface() { }
114
115 ScriptRegistryInterface(ScriptRegistryInterface const&) = delete;
116 ScriptRegistryInterface(ScriptRegistryInterface&&) = delete;
117
118 ScriptRegistryInterface& operator= (ScriptRegistryInterface const&) = delete;
119 ScriptRegistryInterface& operator= (ScriptRegistryInterface&&) = delete;
120
121 /// Removes all scripts associated with the given script context.
122 /// Requires ScriptRegistryBase::SwapContext to be called after all transfers have finished.
123 virtual void ReleaseContext(std::string const& context) = 0;
124
125 /// Injects and updates the changed script objects.
126 virtual void SwapContext(bool initialize) = 0;
127
128 /// Removes the scripts used by this registry from the given container.
129 /// Used to find unused script names.
130 virtual void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) = 0;
131
132 /// Unloads the script registry.
133 virtual void Unload() = 0;
134};
135
136template<class>
137class ScriptRegistry;
138
139class ScriptRegistryCompositum
140 : public ScriptRegistryInterface
141{
142 ScriptRegistryCompositum() { }
143
144 template<class>
145 friend class ScriptRegistry;
146
147 /// Type erasure wrapper for objects
148 class DeleteableObjectBase
149 {
150 public:
151 DeleteableObjectBase() { }
152 virtual ~DeleteableObjectBase() { }
153
154 DeleteableObjectBase(DeleteableObjectBase const&) = delete;
155 DeleteableObjectBase& operator= (DeleteableObjectBase const&) = delete;
156 };
157
158 template<typename T>
159 class DeleteableObject
160 : public DeleteableObjectBase
161 {
162 public:
163 DeleteableObject(T&& object)
164 : _object(std::forward<T>(object)) { }
165
166 private:
167 T _object;
168 };
169
170public:
171 void SetScriptNameInContext(std::string const& scriptname, std::string const& context)
172 {
173 ASSERT(_scriptnames_to_context.find(scriptname) == _scriptnames_to_context.end(),
174 "Scriptname was assigned to this context already!");
175 _scriptnames_to_context.insert(std::make_pair(scriptname, context));
176 }
177
178 std::string const& GetScriptContextOfScriptName(std::string const& scriptname) const
179 {
180 auto itr = _scriptnames_to_context.find(scriptname);
181 ASSERT(itr != _scriptnames_to_context.end() &&
182 "Given scriptname doesn't exist!");
183 return itr->second;
184 }
185
186 void ReleaseContext(std::string const& context) final override
187 {
188 for (auto const registry : _registries)
189 registry->ReleaseContext(context);
190
191 // Clear the script names in context after calling the release hooks
192 // since it's possible that new references to a shared library
193 // are acquired when releasing.
194 for (auto itr = _scriptnames_to_context.begin();
195 itr != _scriptnames_to_context.end();)
196 if (itr->second == context)
197 itr = _scriptnames_to_context.erase(itr);
198 else
199 ++itr;
200 }
201
202 void SwapContext(bool initialize) final override
203 {
204 for (auto const registry : _registries)
205 registry->SwapContext(initialize);
206
207 DoDelayedDelete();
208 }
209
210 void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
211 {
212 for (auto const registry : _registries)
213 registry->RemoveUsedScriptsFromContainer(scripts);
214 }
215
216 void Unload() final override
217 {
218 for (auto const registry : _registries)
219 registry->Unload();
220 }
221
222 template<typename T>
223 void QueueForDelayedDelete(T&& any)
224 {
225 _delayed_delete_queue.push_back(
226 Trinity::make_unique<
227 DeleteableObject<typename std::decay<T>::type>
228 >(std::forward<T>(any))
229 );
230 }
231
232 static ScriptRegistryCompositum* Instance()
233 {
234 static ScriptRegistryCompositum instance;
235 return &instance;
236 }
237
238private:
239 void Register(ScriptRegistryInterface* registry)
240 {
241 _registries.insert(registry);
242 }
243
244 void DoDelayedDelete()
245 {
246 _delayed_delete_queue.clear();
247 }
248
249 std::unordered_set<ScriptRegistryInterface*> _registries;
250
251 std::vector<std::unique_ptr<DeleteableObjectBase>> _delayed_delete_queue;
252
253 std::unordered_map<
254 std::string /*script name*/,
255 std::string /*context*/
256 > _scriptnames_to_context;
257};
258
259#define sScriptRegistryCompositum ScriptRegistryCompositum::Instance()
260
261template<typename /*ScriptType*/, bool /*IsDatabaseBound*/>
262class SpecializedScriptRegistry;
263
264// This is the global static registry of scripts.
265template<class ScriptType>
266class ScriptRegistry final
267 : public SpecializedScriptRegistry<
268 ScriptType, is_script_database_bound<ScriptType>::value>
269{
270 ScriptRegistry()
271 {
272 sScriptRegistryCompositum->Register(this);
273 }
274
275public:
276 static ScriptRegistry* Instance()
277 {
278 static ScriptRegistry instance;
279 return &instance;
280 }
281
282 void LogDuplicatedScriptPointerError(ScriptType const* first, ScriptType const* second)
283 {
284 // See if the script is using the same memory as another script. If this happens, it means that
285 // someone forgot to allocate new memory for a script.
286 TC_LOG_ERROR("scripts", "Script '%s' has same memory pointer as '%s'.",
287 first->GetName().c_str(), second->GetName().c_str());
288 }
289};
290
291class ScriptRegistrySwapHookBase
292{
293public:
294 ScriptRegistrySwapHookBase() { }
295 virtual ~ScriptRegistrySwapHookBase() { }
296
297 ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase const&) = delete;
298 ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase&&) = delete;
299
300 ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase const&) = delete;
301 ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase&&) = delete;
302
303 /// Called before the actual context release happens
304 virtual void BeforeReleaseContext(std::string const& /*context*/) { }
305
306 /// Called before SwapContext
307 virtual void BeforeSwapContext(bool /*initialize*/) { }
308
309 /// Called before Unload
310 virtual void BeforeUnload() { }
311};
312
313template<typename ScriptType, typename Base>
314class ScriptRegistrySwapHooks
315 : public ScriptRegistrySwapHookBase
316{
317};
318
319/// This hook is responsible for swapping OutdoorPvP's
320template<typename Base>
321class UnsupportedScriptRegistrySwapHooks
322 : public ScriptRegistrySwapHookBase
323{
324public:
325 void BeforeReleaseContext(std::string const& context) final override
326 {
327 auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
328 ASSERT(bounds.first == bounds.second);
329 }
330};
331
332/// This hook is responsible for swapping Creature and GameObject AI's
333template<typename ObjectType, typename ScriptType, typename Base>
334class CreatureGameObjectScriptRegistrySwapHooks
335 : public ScriptRegistrySwapHookBase
336{
337 template<typename W>
338 class AIFunctionMapWorker
339 {
340 public:
341 template<typename T>
342 AIFunctionMapWorker(T&& worker)
343 : _worker(std::forward<T>(worker)) { }
344
345 void Visit(std::unordered_map<ObjectGuid, ObjectType*>& objects)
346 {
347 _worker(objects);
348 }
349
350 template<typename O>
351 void Visit(std::unordered_map<ObjectGuid, O*>&) { }
352
353 private:
354 W _worker;
355 };
356
357 class AsyncCastHotswapEffectEvent : public BasicEvent
358 {
359 public:
360 explicit AsyncCastHotswapEffectEvent(Unit* owner) : owner_(owner) { }
361
362 bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
363 {
364 owner_->CastSpell(owner_, SPELL_HOTSWAP_VISUAL_SPELL_EFFECT, true);
365 return true;
366 }
367
368 private:
369 Unit* owner_;
370 };
371
372 // Hook which is called before a creature is swapped
373 static void UnloadStage1(Creature* creature)
374 {
375 creature->m_Events.KillAllEvents(true);
376
377 if (creature->IsCharmed())
378 creature->RemoveCharmedBy(nullptr);
379
380 ASSERT(!creature->IsCharmed(),
381 "There is a disabled AI which is still loaded.");
382
383 creature->AI()->EnterEvadeMode();
384 }
385
386 static void UnloadStage2(Creature* creature)
387 {
388 bool const destroyed = creature->AIM_Destroy();
389 ASSERT(destroyed,
390 "Destroying the AI should never fail here!");
391 (void)destroyed;
392
393 ASSERT(!creature->AI(),
394 "The AI should be null here!");
395 }
396
397 // Hook which is called before a gameobject is swapped
398 static void UnloadStage1(GameObject* gameobject)
399 {
400 gameobject->AI()->Reset();
401 }
402
403 static void UnloadStage2(GameObject* gameobject)
404 {
405 gameobject->AIM_Destroy();
406
407 ASSERT(!gameobject->AI(),
408 "The AI should be null here!");
409 }
410
411 // Hook which is called after a creature was swapped
412 static void LoadStage1(Creature* creature)
413 {
414 ASSERT(!creature->AI(),
415 "The AI should be null here!");
416
417 if (creature->IsAlive())
418 creature->ClearUnitState(UNIT_STATE_EVADE);
419
420 bool const created = creature->AIM_Initialize();
421 ASSERT(created,
422 "Creating the AI should never fail here!");
423 (void)created;
424 }
425
426 static void LoadStage2(Creature* creature)
427 {
428 if (!creature->IsAlive())
429 return;
430
431 creature->AI()->EnterEvadeMode();
432
433 // Cast a dummy visual spell asynchronously here to signal
434 // that the AI was hot swapped
435 creature->m_Events.AddEvent(new AsyncCastHotswapEffectEvent(creature),
436 creature->m_Events.CalculateTime(0));
437 }
438
439 // Hook which is called after a gameobject was swapped
440 static void LoadStage1(GameObject* gameobject)
441 {
442 ASSERT(!gameobject->AI(),
443 "The AI should be null here!");
444
445 gameobject->AIM_Initialize();
446 }
447
448 static void LoadStage2(GameObject* gameobject)
449 {
450 gameobject->AI()->Reset();
451 }
452
453 template<typename T>
454 void RunOverAllEntities(T fn)
455 {
456 auto evaluator = [&](std::unordered_map<ObjectGuid, ObjectType*>& objects)
457 {
458 for (auto object : objects)
459 fn(object.second);
460 };
461
462 AIFunctionMapWorker<typename std::decay<decltype(evaluator)>::type> worker(std::move(evaluator));
463 TypeContainerVisitor<decltype(worker), MapStoredObjectTypesContainer> visitor(worker);
464
465 sMapMgr->DoForAllMaps([&](Map* map)
466 {
467 // Run the worker over all maps
468 visitor.Visit(map->GetObjectsStore());
469 });
470 }
471
472public:
473 void BeforeReleaseContext(std::string const& context) final override
474 {
475 auto ids_to_remove = static_cast<Base*>(this)->GetScriptIDsToRemove(context);
476
477 std::vector<ObjectType*> stage2;
478
479 RunOverAllEntities([&](ObjectType* object)
480 {
481 if (ids_to_remove.find(object->GetScriptId()) != ids_to_remove.end())
482 {
483 UnloadStage1(object);
484 stage2.push_back(object);
485 }
486 });
487
488 for (auto object : stage2)
489 UnloadStage2(object);
490
491 // Add the new ids which are removed to the global ids to remove set
492 ids_removed_.insert(ids_to_remove.begin(), ids_to_remove.end());
493 }
494
495 void BeforeSwapContext(bool initialize) override
496 {
497 // Never swap creature or gameobject scripts when initializing
498 if (initialize)
499 return;
500
501 // Add the recently added scripts to the deleted scripts to replace
502 // default AI's with recently added core scripts.
503 ids_removed_.insert(static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().begin(),
504 static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().end());
505
506 std::vector<ObjectType*> remove;
507 std::vector<ObjectType*> stage2;
508
509 RunOverAllEntities([&](ObjectType* object)
510 {
511 if (ids_removed_.find(object->GetScriptId()) != ids_removed_.end())
512 {
513 if (object->AI())
514 {
515 // Overwrite existing (default) AI's which are replaced by a new script
516 UnloadStage1(object);
517 remove.push_back(object);
518 }
519
520 stage2.push_back(object);
521 }
522 });
523
524 for (auto object : remove)
525 UnloadStage2(object);
526
527 for (auto object : stage2)
528 LoadStage1(object);
529
530 for (auto object : stage2)
531 LoadStage2(object);
532
533 ids_removed_.clear();
534 }
535
536 void BeforeUnload() final override
537 {
538 ASSERT(ids_removed_.empty());
539 }
540
541private:
542 std::unordered_set<uint32> ids_removed_;
543};
544
545// This hook is responsible for swapping CreatureAI's
546template<typename Base>
547class ScriptRegistrySwapHooks<CreatureScript, Base>
548 : public CreatureGameObjectScriptRegistrySwapHooks<
549 Creature, CreatureScript, Base
550 > { };
551
552// This hook is responsible for swapping GameObjectAI's
553template<typename Base>
554class ScriptRegistrySwapHooks<GameObjectScript, Base>
555 : public CreatureGameObjectScriptRegistrySwapHooks<
556 GameObject, GameObjectScript, Base
557 > { };
558
559/// This hook is responsible for swapping BattlegroundScript's
560template<typename Base>
561class ScriptRegistrySwapHooks<BattlegroundScript, Base>
562 : public UnsupportedScriptRegistrySwapHooks<Base> { };
563
564/// This hook is responsible for swapping OutdoorPvP's
565template<typename Base>
566class ScriptRegistrySwapHooks<OutdoorPvPScript, Base>
567 : public ScriptRegistrySwapHookBase
568{
569public:
570 ScriptRegistrySwapHooks() : swapped(false) { }
571
572 void BeforeReleaseContext(std::string const& context) final override
573 {
574 auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
575
576 if ((!swapped) && (bounds.first != bounds.second))
577 {
578 swapped = true;
579 sOutdoorPvPMgr->Die();
580 }
581 }
582
583 void BeforeSwapContext(bool initialize) override
584 {
585 // Never swap outdoor pvp scripts when initializing
586 if ((!initialize) && swapped)
587 {
588 sOutdoorPvPMgr->InitOutdoorPvP();
589 swapped = false;
590 }
591 }
592
593 void BeforeUnload() final override
594 {
595 ASSERT(!swapped);
596 }
597
598private:
599 bool swapped;
600};
601
602/// This hook is responsible for swapping InstanceMapScript's
603template<typename Base>
604class ScriptRegistrySwapHooks<InstanceMapScript, Base>
605 : public ScriptRegistrySwapHookBase
606{
607public:
608 ScriptRegistrySwapHooks() : swapped(false) { }
609
610 void BeforeReleaseContext(std::string const& context) final override
611 {
612 auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
613 if (bounds.first != bounds.second)
614 swapped = true;
615 }
616
617 void BeforeSwapContext(bool /*initialize*/) override
618 {
619 swapped = false;
620 }
621
622 void BeforeUnload() final override
623 {
624 ASSERT(!swapped);
625 }
626
627private:
628 bool swapped;
629};
630
631/// This hook is responsible for swapping SpellScriptLoader's
632template<typename Base>
633class ScriptRegistrySwapHooks<SpellScriptLoader, Base>
634 : public ScriptRegistrySwapHookBase
635{
636public:
637 ScriptRegistrySwapHooks() : swapped(false) { }
638
639 void BeforeReleaseContext(std::string const& context) final override
640 {
641 auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
642
643 if (bounds.first != bounds.second)
644 swapped = true;
645 }
646
647 void BeforeSwapContext(bool /*initialize*/) override
648 {
649 if (swapped)
650 {
651 sObjectMgr->ValidateSpellScripts();
652 swapped = false;
653 }
654 }
655
656 void BeforeUnload() final override
657 {
658 ASSERT(!swapped);
659 }
660
661private:
662 bool swapped;
663};
664
665// Database bound script registry
666template<typename ScriptType>
667class SpecializedScriptRegistry<ScriptType, true>
668 : public ScriptRegistryInterface,
669 public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>>
670{
671 template<typename>
672 friend class UnsupportedScriptRegistrySwapHooks;
673
674 template<typename, typename>
675 friend class ScriptRegistrySwapHooks;
676
677 template<typename, typename, typename>
678 friend class CreatureGameObjectScriptRegistrySwapHooks;
679
680public:
681 SpecializedScriptRegistry() { }
682
683 typedef std::unordered_map<
684 uint32 /*script id*/,
685 std::unique_ptr<ScriptType>
686 > ScriptStoreType;
687
688 typedef typename ScriptStoreType::iterator ScriptStoreIteratorType;
689
690 void ReleaseContext(std::string const& context) final override
691 {
692 this->BeforeReleaseContext(context);
693
694 auto const bounds = _ids_of_contexts.equal_range(context);
695 for (auto itr = bounds.first; itr != bounds.second; ++itr)
696 _scripts.erase(itr->second);
697 }
698
699 void SwapContext(bool initialize) final override
700 {
701 this->BeforeSwapContext(initialize);
702
703 _recently_added_ids.clear();
704 }
705
706 void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
707 {
708 for (auto const& script : _scripts)
709 scripts.erase(script.second->GetName());
710 }
711
712 void Unload() final override
713 {
714 this->BeforeUnload();
715
716 ASSERT(_recently_added_ids.empty(),
717 "Recently added script ids should be empty here!");
718
719 _scripts.clear();
720 _ids_of_contexts.clear();
721 }
722
723 // Adds a database bound script
724 void AddScript(ScriptType* script)
725 {
726 ASSERT(script,
727 "Tried to call AddScript with a nullpointer!");
728 ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(),
729 "Tried to register a script without being in a valid script context!");
730
731 std::unique_ptr<ScriptType> script_ptr(script);
732
733 // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
734 // through a script name (or similar).
735 if (uint32 const id = sObjectMgr->GetScriptId(script->GetName()))
736 {
737 // Try to find an existing script.
738 for (auto const& stored_script : _scripts)
739 {
740 // If the script names match...
741 if (stored_script.second->GetName() == script->GetName())
742 {
743 // If the script is already assigned -> delete it!
744 TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, "
745 "so the script can't work.", script->GetName().c_str());
746
747 // Error that should be fixed ASAP.
748 sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
749 ABORT();
750 return;
751 }
752 }
753
754 // If the script isn't assigned -> assign it!
755 _scripts.insert(std::make_pair(id, std::move(script_ptr)));
756 _ids_of_contexts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), id));
757 _recently_added_ids.insert(id);
758
759 sScriptRegistryCompositum->SetScriptNameInContext(script->GetName(),
760 sScriptMgr->GetCurrentScriptContext());
761 }
762 else
763 {
764 // The script uses a script name from database, but isn't assigned to anything.
765 TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.",
766 script->GetName().c_str());
767
768 // Avoid calling "delete script;" because we are currently in the script constructor
769 // In a valid scenario this will not happen because every script has a name assigned in the database
770 sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
771 return;
772 }
773 }
774
775 // Gets a script by its ID (assigned by ObjectMgr).
776 ScriptType* GetScriptById(uint32 id)
777 {
778 auto const itr = _scripts.find(id);
779 if (itr != _scripts.end())
780 return itr->second.get();
781
782 return nullptr;
783 }
784
785 ScriptStoreType& GetScripts()
786 {
787 return _scripts;
788 }
789
790protected:
791 // Returns the script id's which are registered to a certain context
792 std::unordered_set<uint32> GetScriptIDsToRemove(std::string const& context) const
793 {
794 // Create a set of all ids which are removed
795 std::unordered_set<uint32> scripts_to_remove;
796
797 auto const bounds = _ids_of_contexts.equal_range(context);
798 for (auto itr = bounds.first; itr != bounds.second; ++itr)
799 scripts_to_remove.insert(itr->second);
800
801 return scripts_to_remove;
802 }
803
804 std::unordered_set<uint32> const& GetRecentlyAddedScriptIDs() const
805 {
806 return _recently_added_ids;
807 }
808
809private:
810 ScriptStoreType _scripts;
811
812 // Scripts of a specific context
813 std::unordered_multimap<std::string /*context*/, uint32 /*id*/> _ids_of_contexts;
814
815 // Script id's which were registered recently
816 std::unordered_set<uint32> _recently_added_ids;
817};
818
819/// This hook is responsible for swapping CommandScript's
820template<typename Base>
821class ScriptRegistrySwapHooks<CommandScript, Base>
822 : public ScriptRegistrySwapHookBase
823{
824public:
825 void BeforeReleaseContext(std::string const& /*context*/) final override
826 {
827 ChatHandler::invalidateCommandTable();
828 }
829
830 void BeforeSwapContext(bool /*initialize*/) override
831 {
832 ChatHandler::invalidateCommandTable();
833 }
834
835 void BeforeUnload() final override
836 {
837 ChatHandler::invalidateCommandTable();
838 }
839};
840
841// Database unbound script registry
842template<typename ScriptType>
843class SpecializedScriptRegistry<ScriptType, false>
844 : public ScriptRegistryInterface,
845 public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>>
846{
847 template<typename, typename>
848 friend class ScriptRegistrySwapHooks;
849
850public:
851 typedef std::unordered_multimap<std::string /*context*/, std::unique_ptr<ScriptType>> ScriptStoreType;
852 typedef typename ScriptStoreType::iterator ScriptStoreIteratorType;
853
854 SpecializedScriptRegistry() { }
855
856 void ReleaseContext(std::string const& context) final override
857 {
858 this->BeforeReleaseContext(context);
859
860 _scripts.erase(context);
861 }
862
863 void SwapContext(bool initialize) final override
864 {
865 this->BeforeSwapContext(initialize);
866 }
867
868 void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
869 {
870 for (auto const& script : _scripts)
871 scripts.erase(script.second->GetName());
872 }
873
874 void Unload() final override
875 {
876 this->BeforeUnload();
877
878 _scripts.clear();
879 }
880
881 // Adds a non database bound script
882 void AddScript(ScriptType* script)
883 {
884 ASSERT(script,
885 "Tried to call AddScript with a nullpointer!");
886 ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(),
887 "Tried to register a script without being in a valid script context!");
888
889 std::unique_ptr<ScriptType> script_ptr(script);
890
891 for (auto const& entry : _scripts)
892 if (entry.second.get() == script)
893 {
894 static_cast<ScriptRegistry<ScriptType>*>(this)->
895 LogDuplicatedScriptPointerError(script, entry.second.get());
896
897 sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
898 return;
899 }
900
901 // We're dealing with a code-only script, just add it.
902 _scripts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), std::move(script_ptr)));
903 }
904
905 ScriptStoreType& GetScripts()
906 {
907 return _scripts;
908 }
909
910private:
911 ScriptStoreType _scripts;
912};
913
914// Utility macros to refer to the script registry.
915#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptStoreType
916#define SCR_REG_ITR(T) ScriptRegistry<T>::ScriptStoreIteratorType
917#define SCR_REG_LST(T) ScriptRegistry<T>::Instance()->GetScripts()
918
919// Utility macros for looping over scripts.
920#define FOR_SCRIPTS(T, C, E) \
921 if (SCR_REG_LST(T).empty()) \
922 return; \
923 \
924 for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
925 C != SCR_REG_LST(T).end(); ++C)
926
927#define FOR_SCRIPTS_RET(T, C, E, R) \
928 if (SCR_REG_LST(T).empty()) \
929 return R; \
930 \
931 for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
932 C != SCR_REG_LST(T).end(); ++C)
933
934#define FOREACH_SCRIPT(T) \
935 FOR_SCRIPTS(T, itr, end) \
936 itr->second
937
938// Utility macros for finding specific scripts.
939#define GET_SCRIPT(T, I, V) \
940 T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \
941 if (!V) \
942 return;
943
944#define GET_SCRIPT_RET(T, I, V, R) \
945 T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \
946 if (!V) \
947 return R;
948
949struct TSpellSummary
950{
951 uint8 Targets; // set of enum SelectTarget
952 uint8 Effects; // set of enum SelectEffect
953} *SpellSummary;
954
955ScriptObject::ScriptObject(const char* name) : _name(name)
956{
957 sScriptMgr->IncreaseScriptCount();
958}
959
960ScriptObject::~ScriptObject()
961{
962 sScriptMgr->DecreaseScriptCount();
963}
964
965ScriptMgr::ScriptMgr()
966 : _scriptCount(0), _script_loader_callback(nullptr)
967{
968}
969
970ScriptMgr::~ScriptMgr() { }
971
972ScriptMgr* ScriptMgr::instance()
973{
974 static ScriptMgr instance;
975 return &instance;
976}
977
978void ScriptMgr::Initialize()
979{
980 ASSERT(sSpellMgr->GetSpellInfo(SPELL_HOTSWAP_VISUAL_SPELL_EFFECT)
981 && "Reload hotswap spell effect for creatures isn't valid!");
982
983 uint32 oldMSTime = getMSTime();
984
985 LoadDatabase();
986
987 TC_LOG_INFO("server.loading", "Loading C++ scripts");
988
989 FillSpellSummary();
990
991 // Load core scripts
992 SetScriptContext("___static___");
993
994 // SmartAI
995 AddSC_SmartScripts();
996
997 // LFGScripts
998 lfg::AddSC_LFGScripts();
999
1000 // Load all static linked scripts through the script loader function.
1001 ASSERT(_script_loader_callback,
1002 "Script loader callback wasn't registered!");
1003 _script_loader_callback();
1004
1005 // Initialize all dynamic scripts
1006 // and finishes the context switch to do
1007 // bulk loading
1008 sScriptReloadMgr->Initialize();
1009
1010 // Loads all scripts from the current context
1011 sScriptMgr->SwapScriptContext(true);
1012
1013 // Print unused script names.
1014 std::unordered_set<std::string> unusedScriptNames(
1015 sObjectMgr->GetAllScriptNames().begin(),
1016 sObjectMgr->GetAllScriptNames().end());
1017
1018 // Remove the used scripts from the given container.
1019 sScriptRegistryCompositum->RemoveUsedScriptsFromContainer(unusedScriptNames);
1020
1021 for (std::string const& scriptName : unusedScriptNames)
1022 {
1023 // Avoid complaining about empty script names since the
1024 // script name container contains a placeholder as the 0 element.
1025 if (scriptName.empty())
1026 continue;
1027
1028 TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, "
1029 "but no core script found!", scriptName.c_str());
1030 }
1031
1032 TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms",
1033 GetScriptCount(), GetMSTimeDiffToNow(oldMSTime));
1034}
1035
1036void ScriptMgr::SetScriptContext(std::string const& context)
1037{
1038 _currentContext = context;
1039}
1040
1041void ScriptMgr::SwapScriptContext(bool initialize)
1042{
1043 sScriptRegistryCompositum->SwapContext(initialize);
1044 _currentContext.clear();
1045}
1046
1047void ScriptMgr::ReleaseScriptContext(std::string const& context)
1048{
1049 sScriptRegistryCompositum->ReleaseContext(context);
1050}
1051
1052std::shared_ptr<ModuleReference>
1053 ScriptMgr::AcquireModuleReferenceOfScriptName(std::string const& scriptname) const
1054{
1055#ifdef TRINITY_API_USE_DYNAMIC_LINKING
1056 // Returns the reference to the module of the given scriptname
1057 return ScriptReloadMgr::AcquireModuleReferenceOfContext(
1058 sScriptRegistryCompositum->GetScriptContextOfScriptName(scriptname));
1059#else
1060 (void)scriptname;
1061 // Something went wrong when this function is used in
1062 // a static linked context.
1063 WPAbort();
1064#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
1065}
1066
1067void ScriptMgr::Unload()
1068{
1069 sScriptRegistryCompositum->Unload();
1070
1071 delete[] SpellSummary;
1072 delete[] UnitAI::AISpellInfo;
1073}
1074
1075void ScriptMgr::LoadDatabase()
1076{
1077 sScriptSystemMgr->LoadScriptWaypoints();
1078}
1079
1080void ScriptMgr::FillSpellSummary()
1081{
1082 UnitAI::FillAISpellInfo();
1083
1084 SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()];
1085
1086 SpellInfo const* pTempSpell;
1087
1088 for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
1089 {
1090 SpellSummary[i].Effects = 0;
1091 SpellSummary[i].Targets = 0;
1092
1093 pTempSpell = sSpellMgr->GetSpellInfo(i);
1094 // This spell doesn't exist.
1095 if (!pTempSpell)
1096 continue;
1097
1098 for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
1099 {
1100 // Spell targets self.
1101 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER)
1102 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1);
1103
1104 // Spell targets a single enemy.
1105 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
1106 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY)
1107 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
1108
1109 // Spell targets AoE at enemy.
1110 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
1111 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
1112 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER ||
1113 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
1114 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
1115
1116 // Spell targets an enemy.
1117 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
1118 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY ||
1119 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY ||
1120 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY ||
1121 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER ||
1122 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
1123 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
1124
1125 // Spell targets a single friend (or self).
1126 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER ||
1127 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
1128 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY)
1129 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
1130
1131 // Spell targets AoE friends.
1132 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
1133 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
1134 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER)
1135 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
1136
1137 // Spell targets any friend (or self).
1138 if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER ||
1139 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY ||
1140 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY ||
1141 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY ||
1142 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY ||
1143 pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER)
1144 SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
1145
1146 // Make sure that this spell includes a damage effect.
1147 if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE ||
1148 pTempSpell->Effects[j].Effect == SPELL_EFFECT_INSTAKILL ||
1149 pTempSpell->Effects[j].Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
1150 pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEALTH_LEECH)
1151 SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
1152
1153 // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal).
1154 if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL ||
1155 pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MAX_HEALTH ||
1156 pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MECHANICAL ||
1157 (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && pTempSpell->Effects[j].ApplyAuraName == 8))
1158 SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1);
1159
1160 // Make sure that this spell applies an aura.
1161 if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA)
1162 SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1);
1163 }
1164 }
1165}
1166
1167template<typename T, typename F>
1168void CreateSpellOrAuraScripts(uint32 spellId, std::list<T*>& scriptVector, F&& extractor)
1169{
1170 SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId);
1171
1172 for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr)
1173 {
1174 // When the script is disabled continue with the next one
1175 if (!itr->second.second)
1176 continue;
1177
1178 SpellScriptLoader* tmpscript = sScriptMgr->GetSpellScriptLoader(itr->second.first);
1179 if (!tmpscript)
1180 continue;
1181
1182 T* script = (*tmpscript.*extractor)();
1183
1184 if (!script)
1185 continue;
1186
1187 script->_Init(&tmpscript->GetName(), spellId);
1188
1189 scriptVector.push_back(script);
1190 }
1191}
1192
1193void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector)
1194{
1195 CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetSpellScript);
1196}
1197
1198void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector)
1199{
1200 CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetAuraScript);
1201}
1202
1203SpellScriptLoader* ScriptMgr::GetSpellScriptLoader(uint32 scriptId)
1204{
1205 return ScriptRegistry<SpellScriptLoader>::Instance()->GetScriptById(scriptId);
1206}
1207
1208void ScriptMgr::OnNetworkStart()
1209{
1210 FOREACH_SCRIPT(ServerScript)->OnNetworkStart();
1211}
1212
1213void ScriptMgr::OnNetworkStop()
1214{
1215 FOREACH_SCRIPT(ServerScript)->OnNetworkStop();
1216}
1217
1218void ScriptMgr::OnSocketOpen(std::shared_ptr<WorldSocket> socket)
1219{
1220 ASSERT(socket);
1221
1222 FOREACH_SCRIPT(ServerScript)->OnSocketOpen(socket);
1223}
1224
1225void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> socket)
1226{
1227 ASSERT(socket);
1228
1229 FOREACH_SCRIPT(ServerScript)->OnSocketClose(socket);
1230}
1231
1232void ScriptMgr::OnPacketReceive(WorldSession* session, WorldPacket const& packet)
1233{
1234 if (SCR_REG_LST(ServerScript).empty())
1235 return;
1236
1237 WorldPacket copy(packet);
1238 FOREACH_SCRIPT(ServerScript)->OnPacketReceive(session, copy);
1239}
1240
1241void ScriptMgr::OnPacketSend(WorldSession* session, WorldPacket const& packet)
1242{
1243 ASSERT(session);
1244
1245 if (SCR_REG_LST(ServerScript).empty())
1246 return;
1247
1248 WorldPacket copy(packet);
1249 FOREACH_SCRIPT(ServerScript)->OnPacketSend(session, copy);
1250}
1251
1252void ScriptMgr::OnOpenStateChange(bool open)
1253{
1254#ifdef ELUNA
1255 sEluna->OnOpenStateChange(open);
1256#endif
1257 FOREACH_SCRIPT(WorldScript)->OnOpenStateChange(open);
1258}
1259
1260void ScriptMgr::OnConfigLoad(bool reload)
1261{
1262#ifdef ELUNA
1263 sEluna->OnConfigLoad(reload);
1264#endif
1265 FOREACH_SCRIPT(WorldScript)->OnConfigLoad(reload);
1266}
1267
1268void ScriptMgr::OnMotdChange(std::string& newMotd)
1269{
1270 FOREACH_SCRIPT(WorldScript)->OnMotdChange(newMotd);
1271}
1272
1273void ScriptMgr::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
1274{
1275#ifdef ELUNA
1276 sEluna->OnShutdownInitiate(code, mask);
1277#endif
1278 FOREACH_SCRIPT(WorldScript)->OnShutdownInitiate(code, mask);
1279}
1280
1281void ScriptMgr::OnShutdownCancel()
1282{
1283#ifdef ELUNA
1284 sEluna->OnShutdownCancel();
1285#endif
1286 FOREACH_SCRIPT(WorldScript)->OnShutdownCancel();
1287}
1288
1289void ScriptMgr::OnWorldUpdate(uint32 diff)
1290{
1291#ifdef ELUNA
1292 sEluna->OnWorldUpdate(diff);
1293#endif
1294 FOREACH_SCRIPT(WorldScript)->OnUpdate(diff);
1295}
1296
1297void ScriptMgr::OnHonorCalculation(float& honor, uint8 level, float multiplier)
1298{
1299 FOREACH_SCRIPT(FormulaScript)->OnHonorCalculation(honor, level, multiplier);
1300}
1301
1302void ScriptMgr::OnGrayLevelCalculation(uint8& grayLevel, uint8 playerLevel)
1303{
1304 FOREACH_SCRIPT(FormulaScript)->OnGrayLevelCalculation(grayLevel, playerLevel);
1305}
1306
1307void ScriptMgr::OnColorCodeCalculation(XPColorChar& color, uint8 playerLevel, uint8 mobLevel)
1308{
1309 FOREACH_SCRIPT(FormulaScript)->OnColorCodeCalculation(color, playerLevel, mobLevel);
1310}
1311
1312void ScriptMgr::OnZeroDifferenceCalculation(uint8& diff, uint8 playerLevel)
1313{
1314 FOREACH_SCRIPT(FormulaScript)->OnZeroDifferenceCalculation(diff, playerLevel);
1315}
1316
1317void ScriptMgr::OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content)
1318{
1319 FOREACH_SCRIPT(FormulaScript)->OnBaseGainCalculation(gain, playerLevel, mobLevel, content);
1320}
1321
1322void ScriptMgr::OnGainCalculation(uint32& gain, Player* player, Unit* unit)
1323{
1324 ASSERT(player);
1325 ASSERT(unit);
1326
1327 FOREACH_SCRIPT(FormulaScript)->OnGainCalculation(gain, player, unit);
1328}
1329
1330void ScriptMgr::OnGroupRateCalculation(float& rate, uint32 count, bool isRaid)
1331{
1332 FOREACH_SCRIPT(FormulaScript)->OnGroupRateCalculation(rate, count, isRaid);
1333}
1334
1335#define SCR_MAP_BGN(M, V, I, E, C, T) \
1336 if (V->GetEntry() && V->GetEntry()->T()) \
1337 { \
1338 FOR_SCRIPTS(M, I, E) \
1339 { \
1340 MapEntry const* C = I->second->GetEntry(); \
1341 if (!C) \
1342 continue; \
1343 if (C->MapID == V->GetId()) \
1344 {
1345
1346#define SCR_MAP_END \
1347 return; \
1348 } \
1349 } \
1350 }
1351
1352void ScriptMgr::OnCreateMap(Map* map)
1353{
1354 ASSERT(map);
1355
1356#ifdef ELUNA
1357 sEluna->OnCreate(map);
1358#endif
1359
1360 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1361 itr->second->OnCreate(map);
1362 SCR_MAP_END;
1363
1364 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1365 itr->second->OnCreate((InstanceMap*)map);
1366 SCR_MAP_END;
1367
1368 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1369 itr->second->OnCreate((BattlegroundMap*)map);
1370 SCR_MAP_END;
1371}
1372
1373void ScriptMgr::OnDestroyMap(Map* map)
1374{
1375 ASSERT(map);
1376
1377#ifdef ELUNA
1378 sEluna->OnDestroy(map);
1379#endif
1380
1381 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1382 itr->second->OnDestroy(map);
1383 SCR_MAP_END;
1384
1385 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1386 itr->second->OnDestroy((InstanceMap*)map);
1387 SCR_MAP_END;
1388
1389 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1390 itr->second->OnDestroy((BattlegroundMap*)map);
1391 SCR_MAP_END;
1392}
1393
1394void ScriptMgr::OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
1395{
1396 ASSERT(map);
1397 ASSERT(gmap);
1398
1399 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1400 itr->second->OnLoadGridMap(map, gmap, gx, gy);
1401 SCR_MAP_END;
1402
1403 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1404 itr->second->OnLoadGridMap((InstanceMap*)map, gmap, gx, gy);
1405 SCR_MAP_END;
1406
1407 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1408 itr->second->OnLoadGridMap((BattlegroundMap*)map, gmap, gx, gy);
1409 SCR_MAP_END;
1410}
1411
1412void ScriptMgr::OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
1413{
1414 ASSERT(map);
1415 ASSERT(gmap);
1416
1417 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1418 itr->second->OnUnloadGridMap(map, gmap, gx, gy);
1419 SCR_MAP_END;
1420
1421 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1422 itr->second->OnUnloadGridMap((InstanceMap*)map, gmap, gx, gy);
1423 SCR_MAP_END;
1424
1425 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1426 itr->second->OnUnloadGridMap((BattlegroundMap*)map, gmap, gx, gy);
1427 SCR_MAP_END;
1428}
1429
1430void ScriptMgr::OnPlayerEnterMap(Map* map, Player* player)
1431{
1432 ASSERT(map);
1433 ASSERT(player);
1434
1435#ifdef ELUNA
1436 sEluna->OnMapChanged(player);
1437 sEluna->OnPlayerEnter(map, player);
1438#endif
1439
1440 FOREACH_SCRIPT(PlayerScript)->OnMapChanged(player);
1441
1442 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1443 itr->second->OnPlayerEnter(map, player);
1444 SCR_MAP_END;
1445
1446 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1447 itr->second->OnPlayerEnter((InstanceMap*)map, player);
1448 SCR_MAP_END;
1449
1450 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1451 itr->second->OnPlayerEnter((BattlegroundMap*)map, player);
1452 SCR_MAP_END;
1453}
1454
1455void ScriptMgr::OnPlayerLeaveMap(Map* map, Player* player)
1456{
1457 ASSERT(map);
1458 ASSERT(player);
1459
1460#ifdef ELUNA
1461 sEluna->OnPlayerLeave(map, player);
1462#endif
1463
1464 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1465 itr->second->OnPlayerLeave(map, player);
1466 SCR_MAP_END;
1467
1468 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1469 itr->second->OnPlayerLeave((InstanceMap*)map, player);
1470 SCR_MAP_END;
1471
1472 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1473 itr->second->OnPlayerLeave((BattlegroundMap*)map, player);
1474 SCR_MAP_END;
1475}
1476
1477void ScriptMgr::OnMapUpdate(Map* map, uint32 diff)
1478{
1479 ASSERT(map);
1480
1481#ifdef ELUNA
1482 sEluna->OnUpdate(map, diff);
1483#endif
1484
1485 SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
1486 itr->second->OnUpdate(map, diff);
1487 SCR_MAP_END;
1488
1489 SCR_MAP_BGN(InstanceMapScript, map, itr, end, entry, IsDungeon);
1490 itr->second->OnUpdate((InstanceMap*)map, diff);
1491 SCR_MAP_END;
1492
1493 SCR_MAP_BGN(BattlegroundMapScript, map, itr, end, entry, IsBattleground);
1494 itr->second->OnUpdate((BattlegroundMap*)map, diff);
1495 SCR_MAP_END;
1496}
1497
1498#undef SCR_MAP_BGN
1499#undef SCR_MAP_END
1500
1501InstanceScript* ScriptMgr::CreateInstanceData(InstanceMap* map)
1502{
1503 ASSERT(map);
1504
1505 GET_SCRIPT_RET(InstanceMapScript, map->GetScriptId(), tmpscript, NULL);
1506 return tmpscript->GetInstanceScript(map);
1507}
1508
1509bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Item* target)
1510{
1511 ASSERT(caster);
1512 ASSERT(target);
1513#ifdef ELUNA
1514 if (sEluna->OnDummyEffect(caster, spellId, effIndex, target))
1515 return false;
1516#endif
1517
1518 GET_SCRIPT_RET(ItemScript, target->GetScriptId(), tmpscript, false);
1519 return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
1520}
1521
1522bool ScriptMgr::OnQuestAccept(Player* player, Item* item, Quest const* quest)
1523{
1524 ASSERT(player);
1525 ASSERT(item);
1526 ASSERT(quest);
1527#ifdef ELUNA
1528 if (sEluna->OnQuestAccept(player, item, quest))
1529 return false;
1530#endif
1531
1532 GET_SCRIPT_RET(ItemScript, item->GetScriptId(), tmpscript, false);
1533 player->PlayerTalkClass->ClearMenus();
1534 return tmpscript->OnQuestAccept(player, item, quest);
1535}
1536
1537bool ScriptMgr::OnItemUse(Player* player, Item* item, SpellCastTargets const& targets)
1538{
1539 ASSERT(player);
1540 ASSERT(item);
1541#ifdef ELUNA
1542 if (!sEluna->OnUse(player, item, targets))
1543 return true;
1544#endif
1545
1546 GET_SCRIPT_RET(ItemScript, item->GetScriptId(), tmpscript, false);
1547 return tmpscript->OnUse(player, item, targets);
1548}
1549
1550bool ScriptMgr::OnItemExpire(Player* player, ItemTemplate const* proto)
1551{
1552 ASSERT(player);
1553 ASSERT(proto);
1554#ifdef ELUNA
1555 if (sEluna->OnExpire(player, proto))
1556 return false;
1557#endif
1558
1559 GET_SCRIPT_RET(ItemScript, proto->ScriptId, tmpscript, false);
1560 return tmpscript->OnExpire(player, proto);
1561}
1562
1563bool ScriptMgr::OnItemRemove(Player* player, Item* item)
1564{
1565 ASSERT(player);
1566 ASSERT(item);
1567#ifdef ELUNA
1568 if (sEluna->OnRemove(player, item))
1569 return false;
1570#endif
1571
1572 GET_SCRIPT_RET(ItemScript, item->GetScriptId(), tmpscript, false);
1573 return tmpscript->OnRemove(player, item);
1574}
1575
1576void ScriptMgr::OnGossipSelect(Player* player, Item* item, uint32 sender, uint32 action)
1577{
1578 ASSERT(player);
1579 ASSERT(item);
1580
1581 GET_SCRIPT(ItemScript, item->GetScriptId(), tmpscript);
1582 tmpscript->OnGossipSelect(player, item, sender, action);
1583}
1584
1585void ScriptMgr::OnGossipSelectCode(Player* player, Item* item, uint32 sender, uint32 action, const char* code)
1586{
1587 ASSERT(player);
1588 ASSERT(item);
1589
1590 GET_SCRIPT(ItemScript, item->GetScriptId(), tmpscript);
1591 tmpscript->OnGossipSelectCode(player, item, sender, action, code);
1592}
1593
1594bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, Creature* target)
1595{
1596 ASSERT(caster);
1597 ASSERT(target);
1598#ifdef ELUNA
1599 if (sEluna->OnDummyEffect(caster, spellId, effIndex, target))
1600 return false;
1601#endif
1602
1603 GET_SCRIPT_RET(CreatureScript, target->GetScriptId(), tmpscript, false);
1604 return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
1605}
1606
1607bool ScriptMgr::OnGossipHello(Player* player, Creature* creature)
1608{
1609 ASSERT(player);
1610 ASSERT(creature);
1611#ifdef ELUNA
1612 if (sEluna->OnGossipHello(player, creature))
1613 return true;
1614#endif
1615
1616 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1617 player->PlayerTalkClass->ClearMenus();
1618 return tmpscript->OnGossipHello(player, creature);
1619}
1620
1621bool ScriptMgr::OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
1622{
1623 ASSERT(player);
1624 ASSERT(creature);
1625#ifdef ELUNA
1626 if (sEluna->OnGossipSelect(player, creature, sender, action))
1627 return true;
1628#endif
1629
1630 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1631 return tmpscript->OnGossipSelect(player, creature, sender, action);
1632}
1633
1634bool ScriptMgr::OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
1635{
1636 ASSERT(player);
1637 ASSERT(creature);
1638 ASSERT(code);
1639#ifdef ELUNA
1640 if (sEluna->OnGossipSelectCode(player, creature, sender, action, code))
1641 return true;
1642#endif
1643
1644 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1645 return tmpscript->OnGossipSelectCode(player, creature, sender, action, code);
1646}
1647
1648bool ScriptMgr::OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
1649{
1650 ASSERT(player);
1651 ASSERT(creature);
1652 ASSERT(quest);
1653#ifdef ELUNA
1654 if (sEluna->OnQuestAccept(player, creature, quest))
1655 {
1656 player->PlayerTalkClass->ClearMenus();
1657 return false;
1658 }
1659#endif
1660
1661 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1662 player->PlayerTalkClass->ClearMenus();
1663 return tmpscript->OnQuestAccept(player, creature, quest);
1664}
1665
1666bool ScriptMgr::OnQuestSelect(Player* player, Creature* creature, Quest const* quest)
1667{
1668 ASSERT(player);
1669 ASSERT(creature);
1670 ASSERT(quest);
1671
1672 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1673 player->PlayerTalkClass->ClearMenus();
1674 return tmpscript->OnQuestSelect(player, creature, quest);
1675}
1676
1677bool ScriptMgr::OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt)
1678{
1679 ASSERT(player);
1680 ASSERT(creature);
1681 ASSERT(quest);
1682#ifdef ELUNA
1683 if (sEluna->OnQuestReward(player, creature, quest, opt))
1684 {
1685 player->PlayerTalkClass->ClearMenus();
1686 return false;
1687 }
1688#endif
1689
1690 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, false);
1691 player->PlayerTalkClass->ClearMenus();
1692 return tmpscript->OnQuestReward(player, creature, quest, opt);
1693}
1694
1695uint32 ScriptMgr::GetDialogStatus(Player* player, Creature* creature)
1696{
1697 ASSERT(player);
1698 ASSERT(creature);
1699#ifdef ELUNA
1700 if (uint32 dialogid = sEluna->GetDialogStatus(player, creature))
1701 {
1702 player->PlayerTalkClass->ClearMenus();
1703 return dialogid;
1704 }
1705#endif
1706
1707 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, DIALOG_STATUS_SCRIPTED_NO_STATUS);
1708 player->PlayerTalkClass->ClearMenus();
1709 return tmpscript->GetDialogStatus(player, creature);
1710}
1711
1712CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature)
1713{
1714 ASSERT(creature);
1715#ifdef ELUNA
1716 if (CreatureAI* luaAI = sEluna->GetAI(creature))
1717 return luaAI;
1718#endif
1719
1720 GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, NULL);
1721 return tmpscript->GetAI(creature);
1722}
1723
1724GameObjectAI* ScriptMgr::GetGameObjectAI(GameObject* gameobject)
1725{
1726 ASSERT(gameobject);
1727#ifdef ELUNA
1728 sEluna->OnSpawn(gameobject);
1729#endif
1730
1731 GET_SCRIPT_RET(GameObjectScript, gameobject->GetScriptId(), tmpscript, NULL);
1732 return tmpscript->GetAI(gameobject);
1733}
1734
1735void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff)
1736{
1737 ASSERT(creature);
1738
1739 GET_SCRIPT(CreatureScript, creature->GetScriptId(), tmpscript);
1740 tmpscript->OnUpdate(creature, diff);
1741}
1742
1743bool ScriptMgr::OnGossipHello(Player* player, GameObject* go)
1744{
1745 ASSERT(player);
1746 ASSERT(go);
1747#ifdef ELUNA
1748 if (sEluna->OnGossipHello(player, go))
1749 return true;
1750 if (sEluna->OnGameObjectUse(player, go))
1751 return true;
1752#endif
1753
1754 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
1755 player->PlayerTalkClass->ClearMenus();
1756 return tmpscript->OnGossipHello(player, go);
1757}
1758
1759bool ScriptMgr::OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action)
1760{
1761 ASSERT(player);
1762 ASSERT(go);
1763#ifdef ELUNA
1764 if (sEluna->OnGossipSelect(player, go, sender, action))
1765 return true;
1766#endif
1767
1768 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
1769 return tmpscript->OnGossipSelect(player, go, sender, action);
1770}
1771
1772bool ScriptMgr::OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code)
1773{
1774 ASSERT(player);
1775 ASSERT(go);
1776 ASSERT(code);
1777#ifdef ELUNA
1778 if (sEluna->OnGossipSelectCode(player, go, sender, action, code))
1779 return true;
1780#endif
1781
1782 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
1783 return tmpscript->OnGossipSelectCode(player, go, sender, action, code);
1784}
1785
1786bool ScriptMgr::OnQuestAccept(Player* player, GameObject* go, Quest const* quest)
1787{
1788 ASSERT(player);
1789 ASSERT(go);
1790 ASSERT(quest);
1791#ifdef ELUNA
1792 if (sEluna->OnQuestAccept(player, go, quest))
1793 return false;
1794#endif
1795
1796 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
1797 player->PlayerTalkClass->ClearMenus();
1798 return tmpscript->OnQuestAccept(player, go, quest);
1799}
1800
1801bool ScriptMgr::OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt)
1802{
1803 ASSERT(player);
1804 ASSERT(go);
1805 ASSERT(quest);
1806#ifdef ELUNA
1807 if (sEluna->OnQuestReward(player, go, quest, opt))
1808 return false;
1809#endif
1810
1811 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, false);
1812 player->PlayerTalkClass->ClearMenus();
1813 return tmpscript->OnQuestReward(player, go, quest, opt);
1814}
1815
1816uint32 ScriptMgr::GetDialogStatus(Player* player, GameObject* go)
1817{
1818 ASSERT(player);
1819 ASSERT(go);
1820#ifdef ELUNA
1821 if (uint32 dialogid = sEluna->GetDialogStatus(player, go))
1822 {
1823 player->PlayerTalkClass->ClearMenus();
1824 return dialogid;
1825 }
1826#endif
1827
1828 GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, DIALOG_STATUS_SCRIPTED_NO_STATUS);
1829 player->PlayerTalkClass->ClearMenus();
1830 return tmpscript->GetDialogStatus(player, go);
1831}
1832
1833void ScriptMgr::OnGameObjectDestroyed(GameObject* go, Player* player)
1834{
1835 ASSERT(go);
1836#ifdef ELUNA
1837 sEluna->OnDestroyed(go, player);
1838#endif
1839
1840 GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
1841 tmpscript->OnDestroyed(go, player);
1842}
1843
1844void ScriptMgr::OnGameObjectDamaged(GameObject* go, Player* player)
1845{
1846 ASSERT(go);
1847#ifdef ELUNA
1848 sEluna->OnDamaged(go, player);
1849#endif
1850
1851 GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
1852 tmpscript->OnDamaged(go, player);
1853}
1854
1855void ScriptMgr::OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit)
1856{
1857 ASSERT(go);
1858#ifdef ELUNA
1859 sEluna->OnLootStateChanged(go, state);
1860#endif
1861
1862 GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
1863 tmpscript->OnLootStateChanged(go, state, unit);
1864}
1865
1866void ScriptMgr::OnGameObjectStateChanged(GameObject* go, uint32 state)
1867{
1868 ASSERT(go);
1869#ifdef ELUNA
1870 sEluna->OnGameObjectStateChanged(go, state);
1871#endif
1872
1873 GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
1874 tmpscript->OnGameObjectStateChanged(go, state);
1875}
1876
1877void ScriptMgr::OnGameObjectUpdate(GameObject* go, uint32 diff)
1878{
1879 ASSERT(go);
1880#ifdef ELUNA
1881 sEluna->UpdateAI(go, diff);
1882#endif
1883
1884 GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
1885 tmpscript->OnUpdate(go, diff);
1886}
1887
1888bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex, GameObject* target)
1889{
1890 ASSERT(caster);
1891 ASSERT(target);
1892#ifdef ELUNA
1893 if (sEluna->OnDummyEffect(caster, spellId, effIndex, target))
1894 return false;
1895#endif
1896
1897 GET_SCRIPT_RET(GameObjectScript, target->GetScriptId(), tmpscript, false);
1898 return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
1899}
1900
1901bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger)
1902{
1903 ASSERT(player);
1904 ASSERT(trigger);
1905#ifdef ELUNA
1906 if (sEluna->OnAreaTrigger(player, trigger))
1907 return false;
1908#endif
1909
1910 GET_SCRIPT_RET(AreaTriggerScript, sObjectMgr->GetAreaTriggerScriptId(trigger->id), tmpscript, false);
1911 return tmpscript->OnTrigger(player, trigger);
1912}
1913
1914Battleground* ScriptMgr::CreateBattleground(BattlegroundTypeId /*typeId*/)
1915{
1916 /// @todo Implement script-side battlegrounds.
1917 ABORT();
1918 return NULL;
1919}
1920
1921OutdoorPvP* ScriptMgr::CreateOutdoorPvP(OutdoorPvPData const* data)
1922{
1923 ASSERT(data);
1924
1925 GET_SCRIPT_RET(OutdoorPvPScript, data->ScriptId, tmpscript, NULL);
1926 return tmpscript->GetOutdoorPvP();
1927}
1928
1929std::vector<ChatCommand> ScriptMgr::GetChatCommands()
1930{
1931 std::vector<ChatCommand> table;
1932
1933 FOR_SCRIPTS_RET(CommandScript, itr, end, table)
1934 {
1935 std::vector<ChatCommand> cmds = itr->second->GetCommands();
1936 table.insert(table.end(), cmds.begin(), cmds.end());
1937 }
1938
1939 // Sort commands in alphabetical order
1940 std::sort(table.begin(), table.end(), [](const ChatCommand& a, const ChatCommand&b)
1941 {
1942 return strcmp(a.Name, b.Name) < 0;
1943 });
1944
1945 return table;
1946}
1947
1948void ScriptMgr::OnWeatherChange(Weather* weather, WeatherState state, float grade)
1949{
1950 ASSERT(weather);
1951#ifdef ELUNA
1952 sEluna->OnChange(weather, weather->GetZone(), state, grade);
1953#endif
1954
1955 GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript);
1956 tmpscript->OnChange(weather, state, grade);
1957}
1958
1959void ScriptMgr::OnWeatherUpdate(Weather* weather, uint32 diff)
1960{
1961 ASSERT(weather);
1962
1963 GET_SCRIPT(WeatherScript, weather->GetScriptId(), tmpscript);
1964 tmpscript->OnUpdate(weather, diff);
1965}
1966
1967void ScriptMgr::OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry)
1968{
1969 ASSERT(ah);
1970 ASSERT(entry);
1971#ifdef ELUNA
1972 sEluna->OnAdd(ah, entry);
1973#endif
1974
1975 FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionAdd(ah, entry);
1976}
1977
1978void ScriptMgr::OnAuctionRemove(AuctionHouseObject* ah, AuctionEntry* entry)
1979{
1980 ASSERT(ah);
1981 ASSERT(entry);
1982#ifdef ELUNA
1983 sEluna->OnRemove(ah, entry);
1984#endif
1985
1986 FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionRemove(ah, entry);
1987}
1988
1989void ScriptMgr::OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry)
1990{
1991 ASSERT(ah);
1992 ASSERT(entry);
1993#ifdef ELUNA
1994 sEluna->OnSuccessful(ah, entry);
1995#endif
1996
1997 FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionSuccessful(ah, entry);
1998}
1999
2000void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry)
2001{
2002 ASSERT(ah);
2003 ASSERT(entry);
2004#ifdef ELUNA
2005 sEluna->OnExpire(ah, entry);
2006#endif
2007
2008 FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry);
2009}
2010
2011bool ScriptMgr::OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo)
2012{
2013 ASSERT(condition);
2014
2015 GET_SCRIPT_RET(ConditionScript, condition->ScriptId, tmpscript, true);
2016 return tmpscript->OnConditionCheck(condition, sourceInfo);
2017}
2018
2019void ScriptMgr::OnInstall(Vehicle* veh)
2020{
2021 ASSERT(veh);
2022 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2023#ifdef ELUNA
2024 sEluna->OnInstall(veh);
2025#endif
2026
2027 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2028 tmpscript->OnInstall(veh);
2029}
2030
2031void ScriptMgr::OnUninstall(Vehicle* veh)
2032{
2033 ASSERT(veh);
2034 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2035#ifdef ELUNA
2036 sEluna->OnUninstall(veh);
2037#endif
2038
2039 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2040 tmpscript->OnUninstall(veh);
2041}
2042
2043void ScriptMgr::OnReset(Vehicle* veh)
2044{
2045 ASSERT(veh);
2046 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2047
2048 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2049 tmpscript->OnReset(veh);
2050}
2051
2052void ScriptMgr::OnInstallAccessory(Vehicle* veh, Creature* accessory)
2053{
2054 ASSERT(veh);
2055 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2056 ASSERT(accessory);
2057#ifdef ELUNA
2058 sEluna->OnInstallAccessory(veh, accessory);
2059#endif
2060
2061 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2062 tmpscript->OnInstallAccessory(veh, accessory);
2063}
2064
2065void ScriptMgr::OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId)
2066{
2067 ASSERT(veh);
2068 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2069 ASSERT(passenger);
2070#ifdef ELUNA
2071 sEluna->OnAddPassenger(veh, passenger, seatId);
2072#endif
2073
2074 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2075 tmpscript->OnAddPassenger(veh, passenger, seatId);
2076}
2077
2078void ScriptMgr::OnRemovePassenger(Vehicle* veh, Unit* passenger)
2079{
2080 ASSERT(veh);
2081 ASSERT(veh->GetBase()->GetTypeId() == TYPEID_UNIT);
2082 ASSERT(passenger);
2083#ifdef ELUNA
2084 sEluna->OnRemovePassenger(veh, passenger);
2085#endif
2086
2087 GET_SCRIPT(VehicleScript, veh->GetBase()->ToCreature()->GetScriptId(), tmpscript);
2088 tmpscript->OnRemovePassenger(veh, passenger);
2089}
2090
2091void ScriptMgr::OnDynamicObjectUpdate(DynamicObject* dynobj, uint32 diff)
2092{
2093 ASSERT(dynobj);
2094
2095 FOR_SCRIPTS(DynamicObjectScript, itr, end)
2096 itr->second->OnUpdate(dynobj, diff);
2097}
2098
2099void ScriptMgr::OnAddPassenger(Transport* transport, Player* player)
2100{
2101 ASSERT(transport);
2102 ASSERT(player);
2103
2104 GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
2105 tmpscript->OnAddPassenger(transport, player);
2106}
2107
2108void ScriptMgr::OnAddCreaturePassenger(Transport* transport, Creature* creature)
2109{
2110 ASSERT(transport);
2111 ASSERT(creature);
2112
2113 GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
2114 tmpscript->OnAddCreaturePassenger(transport, creature);
2115}
2116
2117void ScriptMgr::OnRemovePassenger(Transport* transport, Player* player)
2118{
2119 ASSERT(transport);
2120 ASSERT(player);
2121
2122 GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
2123 tmpscript->OnRemovePassenger(transport, player);
2124}
2125
2126void ScriptMgr::OnTransportUpdate(Transport* transport, uint32 diff)
2127{
2128 ASSERT(transport);
2129
2130 GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
2131 tmpscript->OnUpdate(transport, diff);
2132}
2133
2134void ScriptMgr::OnRelocate(Transport* transport, uint32 waypointId, uint32 mapId, float x, float y, float z)
2135{
2136 GET_SCRIPT(TransportScript, transport->GetScriptId(), tmpscript);
2137 tmpscript->OnRelocate(transport, waypointId, mapId, x, y, z);
2138}
2139
2140void ScriptMgr::OnStartup()
2141{
2142#ifdef ELUNA
2143 sEluna->OnStartup();
2144#endif
2145 FOREACH_SCRIPT(WorldScript)->OnStartup();
2146}
2147
2148void ScriptMgr::OnShutdown()
2149{
2150#ifdef ELUNA
2151 sEluna->OnShutdown();
2152#endif
2153 FOREACH_SCRIPT(WorldScript)->OnShutdown();
2154}
2155
2156bool ScriptMgr::OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target)
2157{
2158 ASSERT(source);
2159 // target can be NULL.
2160
2161 GET_SCRIPT_RET(AchievementCriteriaScript, scriptId, tmpscript, false);
2162 return tmpscript->OnCheck(source, target);
2163}
2164
2165// Player
2166void ScriptMgr::OnPVPKill(Player* killer, Player* killed)
2167{
2168#ifdef ELUNA
2169 sEluna->OnPVPKill(killer, killed);
2170#endif
2171 FOREACH_SCRIPT(PlayerScript)->OnPVPKill(killer, killed);
2172}
2173
2174void ScriptMgr::OnCreatureKill(Player* killer, Creature* killed)
2175{
2176#ifdef ELUNA
2177 sEluna->OnCreatureKill(killer, killed);
2178#endif
2179 FOREACH_SCRIPT(PlayerScript)->OnCreatureKill(killer, killed);
2180}
2181
2182void ScriptMgr::OnPlayerKilledByCreature(Creature* killer, Player* killed)
2183{
2184#ifdef ELUNA
2185 sEluna->OnPlayerKilledByCreature(killer, killed);
2186#endif
2187 FOREACH_SCRIPT(PlayerScript)->OnPlayerKilledByCreature(killer, killed);
2188}
2189
2190void ScriptMgr::OnPlayerLevelChanged(Player* player, uint8 oldLevel)
2191{
2192#ifdef ELUNA
2193 sEluna->OnLevelChanged(player, oldLevel);
2194#endif
2195 FOREACH_SCRIPT(PlayerScript)->OnLevelChanged(player, oldLevel);
2196}
2197
2198void ScriptMgr::OnPlayerFreeTalentPointsChanged(Player* player, uint32 points)
2199{
2200#ifdef ELUNA
2201 sEluna->OnFreeTalentPointsChanged(player, points);
2202#endif
2203 FOREACH_SCRIPT(PlayerScript)->OnFreeTalentPointsChanged(player, points);
2204}
2205
2206void ScriptMgr::OnPlayerTalentsReset(Player* player, bool noCost)
2207{
2208#ifdef ELUNA
2209 sEluna->OnTalentsReset(player, noCost);
2210#endif
2211 FOREACH_SCRIPT(PlayerScript)->OnTalentsReset(player, noCost);
2212}
2213
2214void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount)
2215{
2216#ifdef ELUNA
2217 sEluna->OnMoneyChanged(player, amount);
2218#endif
2219 FOREACH_SCRIPT(PlayerScript)->OnMoneyChanged(player, amount);
2220}
2221
2222void ScriptMgr::OnPlayerMoneyLimit(Player* player, int32 amount)
2223{
2224 FOREACH_SCRIPT(PlayerScript)->OnMoneyLimit(player, amount);
2225}
2226
2227void ScriptMgr::OnGivePlayerXP(Player* player, uint32& amount, Unit* victim)
2228{
2229#ifdef ELUNA
2230 sEluna->OnGiveXP(player, amount, victim);
2231#endif
2232 FOREACH_SCRIPT(PlayerScript)->OnGiveXP(player, amount, victim);
2233}
2234
2235void ScriptMgr::OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental)
2236{
2237#ifdef ELUNA
2238 sEluna->OnReputationChange(player, factionID, standing, incremental);
2239#endif
2240 FOREACH_SCRIPT(PlayerScript)->OnReputationChange(player, factionID, standing, incremental);
2241}
2242
2243void ScriptMgr::OnPlayerDuelRequest(Player* target, Player* challenger)
2244{
2245#ifdef ELUNA
2246 sEluna->OnDuelRequest(target, challenger);
2247#endif
2248 FOREACH_SCRIPT(PlayerScript)->OnDuelRequest(target, challenger);
2249}
2250
2251void ScriptMgr::OnPlayerDuelStart(Player* player1, Player* player2)
2252{
2253#ifdef ELUNA
2254 sEluna->OnDuelStart(player1, player2);
2255#endif
2256 FOREACH_SCRIPT(PlayerScript)->OnDuelStart(player1, player2);
2257}
2258
2259void ScriptMgr::OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type)
2260{
2261#ifdef ELUNA
2262 sEluna->OnDuelEnd(winner, loser, type);
2263#endif
2264 FOREACH_SCRIPT(PlayerScript)->OnDuelEnd(winner, loser, type);
2265}
2266
2267void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg)
2268{
2269 FOREACH_SCRIPT(PlayerScript)->OnChat(player, type, lang, msg);
2270}
2271
2272void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver)
2273{
2274 FOREACH_SCRIPT(PlayerScript)->OnChat(player, type, lang, msg, receiver);
2275}
2276
2277void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group)
2278{
2279 FOREACH_SCRIPT(PlayerScript)->OnChat(player, type, lang, msg, group);
2280}
2281
2282void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild)
2283{
2284 FOREACH_SCRIPT(PlayerScript)->OnChat(player, type, lang, msg, guild);
2285}
2286
2287void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel)
2288{
2289 FOREACH_SCRIPT(PlayerScript)->OnChat(player, type, lang, msg, channel);
2290}
2291
2292void ScriptMgr::OnPlayerEmote(Player* player, uint32 emote)
2293{
2294#ifdef ELUNA
2295 sEluna->OnEmote(player, emote);
2296#endif
2297 FOREACH_SCRIPT(PlayerScript)->OnEmote(player, emote);
2298}
2299
2300void ScriptMgr::OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid)
2301{
2302#ifdef ELUNA
2303 sEluna->OnTextEmote(player, textEmote, emoteNum, guid);
2304#endif
2305 FOREACH_SCRIPT(PlayerScript)->OnTextEmote(player, textEmote, emoteNum, guid);
2306}
2307
2308void ScriptMgr::OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck)
2309{
2310#ifdef ELUNA
2311 sEluna->OnSpellCast(player, spell, skipCheck);
2312#endif
2313 FOREACH_SCRIPT(PlayerScript)->OnSpellCast(player, spell, skipCheck);
2314}
2315
2316void ScriptMgr::OnPlayerLogin(Player* player, bool firstLogin)
2317{
2318#ifdef ELUNA
2319 if (firstLogin)
2320 sEluna->OnFirstLogin(player);
2321 sEluna->OnLogin(player);
2322#endif
2323 FOREACH_SCRIPT(PlayerScript)->OnLogin(player, firstLogin);
2324}
2325
2326void ScriptMgr::OnPlayerLogout(Player* player)
2327{
2328#ifdef ELUNA
2329 sEluna->OnLogout(player);
2330#endif
2331 FOREACH_SCRIPT(PlayerScript)->OnLogout(player);
2332}
2333
2334void ScriptMgr::OnPlayerCreate(Player* player)
2335{
2336#ifdef ELUNA
2337 sEluna->OnCreate(player);
2338#endif
2339 FOREACH_SCRIPT(PlayerScript)->OnCreate(player);
2340}
2341
2342void ScriptMgr::OnPlayerDelete(ObjectGuid guid, uint32 accountId)
2343{
2344#ifdef ELUNA
2345 sEluna->OnDelete(GUID_LOPART(guid));
2346#endif
2347 FOREACH_SCRIPT(PlayerScript)->OnDelete(guid, accountId);
2348}
2349
2350void ScriptMgr::OnPlayerFailedDelete(ObjectGuid guid, uint32 accountId)
2351{
2352 FOREACH_SCRIPT(PlayerScript)->OnFailedDelete(guid, accountId);
2353}
2354
2355void ScriptMgr::OnPlayerSave(Player* player)
2356{
2357#ifdef ELUNA
2358 sEluna->OnSave(player);
2359#endif
2360 FOREACH_SCRIPT(PlayerScript)->OnSave(player);
2361}
2362
2363void ScriptMgr::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent, uint8 extendState)
2364{
2365#ifdef ELUNA
2366 sEluna->OnBindToInstance(player, difficulty, mapid, permanent);
2367#endif
2368 FOREACH_SCRIPT(PlayerScript)->OnBindToInstance(player, difficulty, mapid, permanent, extendState);
2369}
2370
2371void ScriptMgr::OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea)
2372{
2373#ifdef ELUNA
2374 sEluna->OnUpdateZone(player, newZone, newArea);
2375#endif
2376 FOREACH_SCRIPT(PlayerScript)->OnUpdateZone(player, newZone, newArea);
2377}
2378
2379void ScriptMgr::OnGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action)
2380{
2381 FOREACH_SCRIPT(PlayerScript)->OnGossipSelect(player, menu_id, sender, action);
2382}
2383
2384void ScriptMgr::OnGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code)
2385{
2386 FOREACH_SCRIPT(PlayerScript)->OnGossipSelectCode(player, menu_id, sender, action, code);
2387}
2388
2389void ScriptMgr::OnQuestStatusChange(Player* player, uint32 questId, QuestStatus status)
2390{
2391 FOREACH_SCRIPT(PlayerScript)->OnQuestStatusChange(player, questId, status);
2392}
2393
2394// Account
2395void ScriptMgr::OnAccountLogin(uint32 accountId)
2396{
2397 FOREACH_SCRIPT(AccountScript)->OnAccountLogin(accountId);
2398}
2399
2400void ScriptMgr::OnFailedAccountLogin(uint32 accountId)
2401{
2402 FOREACH_SCRIPT(AccountScript)->OnFailedAccountLogin(accountId);
2403}
2404
2405void ScriptMgr::OnEmailChange(uint32 accountId)
2406{
2407 FOREACH_SCRIPT(AccountScript)->OnEmailChange(accountId);
2408}
2409
2410void ScriptMgr::OnFailedEmailChange(uint32 accountId)
2411{
2412 FOREACH_SCRIPT(AccountScript)->OnFailedEmailChange(accountId);
2413}
2414
2415void ScriptMgr::OnPasswordChange(uint32 accountId)
2416{
2417 FOREACH_SCRIPT(AccountScript)->OnPasswordChange(accountId);
2418}
2419
2420void ScriptMgr::OnFailedPasswordChange(uint32 accountId)
2421{
2422 FOREACH_SCRIPT(AccountScript)->OnFailedPasswordChange(accountId);
2423}
2424
2425// Guild
2426void ScriptMgr::OnGuildAddMember(Guild* guild, Player* player, uint8& plRank)
2427{
2428#ifdef ELUNA
2429 sEluna->OnAddMember(guild, player, plRank);
2430#endif
2431 FOREACH_SCRIPT(GuildScript)->OnAddMember(guild, player, plRank);
2432}
2433
2434void ScriptMgr::OnGuildRemoveMember(Guild* guild, Player* player, bool isDisbanding, bool isKicked)
2435{
2436#ifdef ELUNA
2437 sEluna->OnRemoveMember(guild, player, isDisbanding);
2438#endif
2439 FOREACH_SCRIPT(GuildScript)->OnRemoveMember(guild, player, isDisbanding, isKicked);
2440}
2441
2442void ScriptMgr::OnGuildMOTDChanged(Guild* guild, const std::string& newMotd)
2443{
2444#ifdef ELUNA
2445 sEluna->OnMOTDChanged(guild, newMotd);
2446#endif
2447 FOREACH_SCRIPT(GuildScript)->OnMOTDChanged(guild, newMotd);
2448}
2449
2450void ScriptMgr::OnGuildInfoChanged(Guild* guild, const std::string& newInfo)
2451{
2452#ifdef ELUNA
2453 sEluna->OnInfoChanged(guild, newInfo);
2454#endif
2455 FOREACH_SCRIPT(GuildScript)->OnInfoChanged(guild, newInfo);
2456}
2457
2458void ScriptMgr::OnGuildCreate(Guild* guild, Player* leader, const std::string& name)
2459{
2460#ifdef ELUNA
2461 sEluna->OnCreate(guild, leader, name);
2462#endif
2463 FOREACH_SCRIPT(GuildScript)->OnCreate(guild, leader, name);
2464}
2465
2466void ScriptMgr::OnGuildDisband(Guild* guild)
2467{
2468#ifdef ELUNA
2469 sEluna->OnDisband(guild);
2470#endif
2471 FOREACH_SCRIPT(GuildScript)->OnDisband(guild);
2472}
2473
2474void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair)
2475{
2476#ifdef ELUNA
2477 sEluna->OnMemberWitdrawMoney(guild, player, amount, isRepair);
2478#endif
2479 FOREACH_SCRIPT(GuildScript)->OnMemberWitdrawMoney(guild, player, amount, isRepair);
2480}
2481
2482void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount)
2483{
2484#ifdef ELUNA
2485 sEluna->OnMemberDepositMoney(guild, player, amount);
2486#endif
2487 FOREACH_SCRIPT(GuildScript)->OnMemberDepositMoney(guild, player, amount);
2488}
2489
2490void ScriptMgr::OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
2491 bool isDestBank, uint8 destContainer, uint8 destSlotId)
2492{
2493#ifdef ELUNA
2494 sEluna->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId);
2495#endif
2496 FOREACH_SCRIPT(GuildScript)->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId);
2497}
2498
2499void ScriptMgr::OnGuildEvent(Guild* guild, uint8 eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank)
2500{
2501#ifdef ELUNA
2502 sEluna->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank);
2503#endif
2504 FOREACH_SCRIPT(GuildScript)->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank);
2505}
2506
2507void ScriptMgr::OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
2508{
2509#ifdef ELUNA
2510 sEluna->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId);
2511#endif
2512 FOREACH_SCRIPT(GuildScript)->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId);
2513}
2514
2515// Group
2516void ScriptMgr::OnGroupAddMember(Group* group, ObjectGuid guid)
2517{
2518 ASSERT(group);
2519#ifdef ELUNA
2520 sEluna->OnAddMember(group, guid);
2521#endif
2522 FOREACH_SCRIPT(GroupScript)->OnAddMember(group, guid);
2523}
2524
2525void ScriptMgr::OnGroupInviteMember(Group* group, ObjectGuid guid)
2526{
2527 ASSERT(group);
2528#ifdef ELUNA
2529 sEluna->OnInviteMember(group, guid);
2530#endif
2531 FOREACH_SCRIPT(GroupScript)->OnInviteMember(group, guid);
2532}
2533
2534void ScriptMgr::OnGroupRemoveMember(Group* group, ObjectGuid guid, RemoveMethod method, ObjectGuid kicker, const char* reason)
2535{
2536 ASSERT(group);
2537#ifdef ELUNA
2538 sEluna->OnRemoveMember(group, guid, method);
2539#endif
2540 FOREACH_SCRIPT(GroupScript)->OnRemoveMember(group, guid, method, kicker, reason);
2541}
2542
2543void ScriptMgr::OnGroupChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid)
2544{
2545 ASSERT(group);
2546#ifdef ELUNA
2547 sEluna->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid);
2548#endif
2549 FOREACH_SCRIPT(GroupScript)->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid);
2550}
2551
2552void ScriptMgr::OnGroupDisband(Group* group)
2553{
2554 ASSERT(group);
2555#ifdef ELUNA
2556 sEluna->OnDisband(group);
2557#endif
2558 FOREACH_SCRIPT(GroupScript)->OnDisband(group);
2559}
2560
2561// Unit
2562void ScriptMgr::OnHeal(Unit* healer, Unit* reciever, uint32& gain)
2563{
2564 FOREACH_SCRIPT(UnitScript)->OnHeal(healer, reciever, gain);
2565 FOREACH_SCRIPT(PlayerScript)->OnHeal(healer, reciever, gain);
2566}
2567
2568void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32& damage)
2569{
2570 FOREACH_SCRIPT(UnitScript)->OnDamage(attacker, victim, damage);
2571 FOREACH_SCRIPT(PlayerScript)->OnDamage(attacker, victim, damage);
2572}
2573
2574void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage)
2575{
2576 FOREACH_SCRIPT(UnitScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage);
2577 FOREACH_SCRIPT(PlayerScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage);
2578}
2579
2580void ScriptMgr::ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage)
2581{
2582 FOREACH_SCRIPT(UnitScript)->ModifyMeleeDamage(target, attacker, damage);
2583 FOREACH_SCRIPT(PlayerScript)->ModifyMeleeDamage(target, attacker, damage);
2584}
2585
2586void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage)
2587{
2588 FOREACH_SCRIPT(UnitScript)->ModifySpellDamageTaken(target, attacker, damage);
2589 FOREACH_SCRIPT(PlayerScript)->ModifySpellDamageTaken(target, attacker, damage);
2590}
2591
2592SpellScriptLoader::SpellScriptLoader(const char* name)
2593 : ScriptObject(name)
2594{
2595 ScriptRegistry<SpellScriptLoader>::Instance()->AddScript(this);
2596}
2597
2598ServerScript::ServerScript(const char* name)
2599 : ScriptObject(name)
2600{
2601 ScriptRegistry<ServerScript>::Instance()->AddScript(this);
2602}
2603
2604WorldScript::WorldScript(const char* name)
2605 : ScriptObject(name)
2606{
2607 ScriptRegistry<WorldScript>::Instance()->AddScript(this);
2608}
2609
2610FormulaScript::FormulaScript(const char* name)
2611 : ScriptObject(name)
2612{
2613 ScriptRegistry<FormulaScript>::Instance()->AddScript(this);
2614}
2615
2616UnitScript::UnitScript(const char* name, bool addToScripts)
2617 : ScriptObject(name)
2618{
2619 if (addToScripts)
2620 ScriptRegistry<UnitScript>::Instance()->AddScript(this);
2621}
2622
2623WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
2624 : ScriptObject(name), MapScript<Map>(mapId)
2625{
2626 if (GetEntry() && !GetEntry()->IsWorldMap())
2627 TC_LOG_ERROR("scripts", "WorldMapScript for map %u is invalid.", mapId);
2628
2629 ScriptRegistry<WorldMapScript>::Instance()->AddScript(this);
2630}
2631
2632InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId)
2633 : ScriptObject(name), MapScript<InstanceMap>(mapId)
2634{
2635 if (GetEntry() && !GetEntry()->IsDungeon())
2636 TC_LOG_ERROR("scripts", "InstanceMapScript for map %u is invalid.", mapId);
2637
2638 ScriptRegistry<InstanceMapScript>::Instance()->AddScript(this);
2639}
2640
2641BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId)
2642 : ScriptObject(name), MapScript<BattlegroundMap>(mapId)
2643{
2644 if (GetEntry() && !GetEntry()->IsBattleground())
2645 TC_LOG_ERROR("scripts", "BattlegroundMapScript for map %u is invalid.", mapId);
2646
2647 ScriptRegistry<BattlegroundMapScript>::Instance()->AddScript(this);
2648}
2649
2650ItemScript::ItemScript(const char* name)
2651 : ScriptObject(name)
2652{
2653 ScriptRegistry<ItemScript>::Instance()->AddScript(this);
2654}
2655
2656CreatureScript::CreatureScript(const char* name)
2657 : UnitScript(name, false)
2658{
2659 ScriptRegistry<CreatureScript>::Instance()->AddScript(this);
2660}
2661
2662GameObjectScript::GameObjectScript(const char* name)
2663 : ScriptObject(name)
2664{
2665 ScriptRegistry<GameObjectScript>::Instance()->AddScript(this);
2666}
2667
2668AreaTriggerScript::AreaTriggerScript(const char* name)
2669 : ScriptObject(name)
2670{
2671 ScriptRegistry<AreaTriggerScript>::Instance()->AddScript(this);
2672}
2673
2674BattlegroundScript::BattlegroundScript(const char* name)
2675 : ScriptObject(name)
2676{
2677 ScriptRegistry<BattlegroundScript>::Instance()->AddScript(this);
2678}
2679
2680OutdoorPvPScript::OutdoorPvPScript(const char* name)
2681 : ScriptObject(name)
2682{
2683 ScriptRegistry<OutdoorPvPScript>::Instance()->AddScript(this);
2684}
2685
2686CommandScript::CommandScript(const char* name)
2687 : ScriptObject(name)
2688{
2689 ScriptRegistry<CommandScript>::Instance()->AddScript(this);
2690}
2691
2692WeatherScript::WeatherScript(const char* name)
2693 : ScriptObject(name)
2694{
2695 ScriptRegistry<WeatherScript>::Instance()->AddScript(this);
2696}
2697
2698AuctionHouseScript::AuctionHouseScript(const char* name)
2699 : ScriptObject(name)
2700{
2701 ScriptRegistry<AuctionHouseScript>::Instance()->AddScript(this);
2702}
2703
2704ConditionScript::ConditionScript(const char* name)
2705 : ScriptObject(name)
2706{
2707 ScriptRegistry<ConditionScript>::Instance()->AddScript(this);
2708}
2709
2710VehicleScript::VehicleScript(const char* name)
2711 : ScriptObject(name)
2712{
2713 ScriptRegistry<VehicleScript>::Instance()->AddScript(this);
2714}
2715
2716DynamicObjectScript::DynamicObjectScript(const char* name)
2717 : ScriptObject(name)
2718{
2719 ScriptRegistry<DynamicObjectScript>::Instance()->AddScript(this);
2720}
2721
2722TransportScript::TransportScript(const char* name)
2723 : ScriptObject(name)
2724{
2725 ScriptRegistry<TransportScript>::Instance()->AddScript(this);
2726}
2727
2728AchievementCriteriaScript::AchievementCriteriaScript(const char* name)
2729 : ScriptObject(name)
2730{
2731 ScriptRegistry<AchievementCriteriaScript>::Instance()->AddScript(this);
2732}
2733
2734PlayerScript::PlayerScript(const char* name)
2735 : UnitScript(name, false)
2736{
2737 ScriptRegistry<PlayerScript>::Instance()->AddScript(this);
2738}
2739
2740AccountScript::AccountScript(const char* name)
2741 : ScriptObject(name)
2742{
2743 ScriptRegistry<AccountScript>::Instance()->AddScript(this);
2744}
2745
2746GuildScript::GuildScript(const char* name)
2747 : ScriptObject(name)
2748{
2749 ScriptRegistry<GuildScript>::Instance()->AddScript(this);
2750}
2751
2752GroupScript::GroupScript(const char* name)
2753 : ScriptObject(name)
2754{
2755 ScriptRegistry<GroupScript>::Instance()->AddScript(this);
2756}
2757
2758// Specialize for each script type class like so:
2759template class TC_GAME_API ScriptRegistry<SpellScriptLoader>;
2760template class TC_GAME_API ScriptRegistry<ServerScript>;
2761template class TC_GAME_API ScriptRegistry<WorldScript>;
2762template class TC_GAME_API ScriptRegistry<FormulaScript>;
2763template class TC_GAME_API ScriptRegistry<WorldMapScript>;
2764template class TC_GAME_API ScriptRegistry<InstanceMapScript>;
2765template class TC_GAME_API ScriptRegistry<BattlegroundMapScript>;
2766template class TC_GAME_API ScriptRegistry<ItemScript>;
2767template class TC_GAME_API ScriptRegistry<CreatureScript>;
2768template class TC_GAME_API ScriptRegistry<GameObjectScript>;
2769template class TC_GAME_API ScriptRegistry<AreaTriggerScript>;
2770template class TC_GAME_API ScriptRegistry<BattlegroundScript>;
2771template class TC_GAME_API ScriptRegistry<OutdoorPvPScript>;
2772template class TC_GAME_API ScriptRegistry<CommandScript>;
2773template class TC_GAME_API ScriptRegistry<WeatherScript>;
2774template class TC_GAME_API ScriptRegistry<AuctionHouseScript>;
2775template class TC_GAME_API ScriptRegistry<ConditionScript>;
2776template class TC_GAME_API ScriptRegistry<VehicleScript>;
2777template class TC_GAME_API ScriptRegistry<DynamicObjectScript>;
2778template class TC_GAME_API ScriptRegistry<TransportScript>;
2779template class TC_GAME_API ScriptRegistry<AchievementCriteriaScript>;
2780template class TC_GAME_API ScriptRegistry<PlayerScript>;
2781template class TC_GAME_API ScriptRegistry<GuildScript>;
2782template class TC_GAME_API ScriptRegistry<GroupScript>;
2783template class TC_GAME_API ScriptRegistry<UnitScript>;
2784template class TC_GAME_API ScriptRegistry<AccountScript>;