summaryrefslogtreecommitdiff
path: root/src/server/game/Scripting/ScriptMgr.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Scripting/ScriptMgr.h')
-rw-r--r--src/server/game/Scripting/ScriptMgr.h1114
1 files changed, 1114 insertions, 0 deletions
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
new file mode 100644
index 0000000000..df6f6a7f3e
--- /dev/null
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (C)
+ * Copyright (C)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SC_SCRIPTMGR_H
+#define SC_SCRIPTMGR_H
+
+#include "Common.h"
+#include <ace/Singleton.h>
+#include <ace/Atomic_Op.h>
+
+#include "ObjectMgr.h"
+#include "DBCStores.h"
+#include "QuestDef.h"
+#include "SharedDefines.h"
+#include "World.h"
+#include "Weather.h"
+
+class AuctionHouseObject;
+class AuraScript;
+class Battleground;
+class BattlegroundMap;
+class Channel;
+class ChatCommand;
+class Creature;
+class CreatureAI;
+class DynamicObject;
+class GameObject;
+class GameObjectAI;
+class Guild;
+class GridMap;
+class Group;
+class InstanceMap;
+class InstanceScript;
+class Item;
+class Map;
+class OutdoorPvP;
+class Player;
+class Quest;
+class ScriptMgr;
+class Spell;
+class SpellScript;
+class SpellCastTargets;
+class Transport;
+class StaticTransport;
+class MotionTransport;
+class Unit;
+class Vehicle;
+class WorldPacket;
+class WorldSocket;
+class WorldObject;
+
+struct AchievementCriteriaData;
+struct AuctionEntry;
+struct ConditionSourceInfo;
+struct Condition;
+struct ItemTemplate;
+struct OutdoorPvPData;
+
+#define VISIBLE_RANGE 166.0f //MAX visible range (size of grid)
+
+
+/*
+ TODO: Add more script type classes.
+
+ MailScript
+ SessionScript
+ CollisionScript
+ ArenaTeamScript
+
+*/
+
+/*
+ Standard procedure when adding new script type classes:
+
+ First of all, define the actual class, and have it inherit from ScriptObject, like so:
+
+ class MyScriptType : public ScriptObject
+ {
+ uint32 _someId;
+
+ private:
+
+ void RegisterSelf();
+
+ protected:
+
+ MyScriptType(const char* name, uint32 someId)
+ : ScriptObject(name), _someId(someId)
+ {
+ ScriptRegistry<MyScriptType>::AddScript(this);
+ }
+
+ public:
+
+ // If a virtual function in your script type class is not necessarily
+ // required to be overridden, just declare it virtual with an empty
+ // body. If, on the other hand, it's logical only to override it (i.e.
+ // if it's the only method in the class), make it pure virtual, by adding
+ // = 0 to it.
+ virtual void OnSomeEvent(uint32 someArg1, std::string& someArg2) { }
+
+ // This is a pure virtual function:
+ virtual void OnAnotherEvent(uint32 someArg) = 0;
+ }
+
+ Next, you need to add a specialization for ScriptRegistry. Put this in the bottom of
+ ScriptMgr.cpp:
+
+ template class ScriptRegistry<MyScriptType>;
+
+ Now, add a cleanup routine in ScriptMgr::~ScriptMgr:
+
+ SCR_CLEAR(MyScriptType);
+
+ Now your script type is good to go with the script system. What you need to do now
+ is add functions to ScriptMgr that can be called from the core to actually trigger
+ certain events. For example, in ScriptMgr.h:
+
+ void OnSomeEvent(uint32 someArg1, std::string& someArg2);
+ void OnAnotherEvent(uint32 someArg);
+
+ In ScriptMgr.cpp:
+
+ void ScriptMgr::OnSomeEvent(uint32 someArg1, std::string& someArg2)
+ {
+ FOREACH_SCRIPT(MyScriptType)->OnSomeEvent(someArg1, someArg2);
+ }
+
+ void ScriptMgr::OnAnotherEvent(uint32 someArg)
+ {
+ FOREACH_SCRIPT(MyScriptType)->OnAnotherEvent(someArg1, someArg2);
+ }
+
+ Now you simply call these two functions from anywhere in the core to trigger the
+ event on all registered scripts of that type.
+*/
+
+class ScriptObject
+{
+ friend class ScriptMgr;
+
+ public:
+
+ // Do not override this in scripts; it should be overridden by the various script type classes. It indicates
+ // whether or not this script type must be assigned in the database.
+ virtual bool IsDatabaseBound() const { return false; }
+
+ const std::string& GetName() const { return _name; }
+
+ protected:
+
+ ScriptObject(const char* name)
+ : _name(std::string(name))
+ {
+ }
+
+ virtual ~ScriptObject()
+ {
+ }
+
+ private:
+
+ const std::string _name;
+};
+
+template<class TObject> class UpdatableScript
+{
+ protected:
+
+ UpdatableScript()
+ {
+ }
+
+ public:
+
+ virtual void OnUpdate(TObject* /*obj*/, uint32 /*diff*/) { }
+};
+
+class SpellScriptLoader : public ScriptObject
+{
+ protected:
+
+ SpellScriptLoader(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Should return a fully valid SpellScript pointer.
+ virtual SpellScript* GetSpellScript() const { return NULL; }
+
+ // Should return a fully valid AuraScript pointer.
+ virtual AuraScript* GetAuraScript() const { return NULL; }
+};
+
+class ServerScript : public ScriptObject
+{
+ protected:
+
+ ServerScript(const char* name);
+
+ public:
+
+ // Called when reactive socket I/O is started (WorldSocketMgr).
+ virtual void OnNetworkStart() { }
+
+ // Called when reactive I/O is stopped.
+ virtual void OnNetworkStop() { }
+
+ // Called when a remote socket establishes a connection to the server. Do not store the socket object.
+ virtual void OnSocketOpen(WorldSocket* /*socket*/) { }
+
+ // Called when a socket is closed. Do not store the socket object, and do not rely on the connection
+ // being open; it is not.
+ virtual void OnSocketClose(WorldSocket* /*socket*/, bool /*wasNew*/) { }
+};
+
+class WorldScript : public ScriptObject
+{
+ protected:
+
+ WorldScript(const char* name);
+
+ public:
+
+ // Called when the open/closed state of the world changes.
+ virtual void OnOpenStateChange(bool /*open*/) { }
+
+ // Called after the world configuration is (re)loaded.
+ virtual void OnConfigLoad(bool /*reload*/) { }
+
+ // Called before the message of the day is changed.
+ virtual void OnMotdChange(std::string& /*newMotd*/) { }
+
+ // Called when a world shutdown is initiated.
+ virtual void OnShutdownInitiate(ShutdownExitCode /*code*/, ShutdownMask /*mask*/) { }
+
+ // Called when a world shutdown is cancelled.
+ virtual void OnShutdownCancel() { }
+
+ // Called on every world tick (don't execute too heavy code here).
+ virtual void OnUpdate(uint32 /*diff*/) { }
+
+ // Called when the world is started.
+ virtual void OnStartup() { }
+
+ // Called when the world is actually shut down.
+ virtual void OnShutdown() { }
+};
+
+class FormulaScript : public ScriptObject
+{
+ protected:
+
+ FormulaScript(const char* name);
+
+ public:
+
+ // Called after calculating honor.
+ virtual void OnHonorCalculation(float& /*honor*/, uint8 /*level*/, float /*multiplier*/) { }
+
+ // Called after gray level calculation.
+ virtual void OnGrayLevelCalculation(uint8& /*grayLevel*/, uint8 /*playerLevel*/) { }
+
+ // Called after calculating experience color.
+ virtual void OnColorCodeCalculation(XPColorChar& /*color*/, uint8 /*playerLevel*/, uint8 /*mobLevel*/) { }
+
+ // Called after calculating zero difference.
+ virtual void OnZeroDifferenceCalculation(uint8& /*diff*/, uint8 /*playerLevel*/) { }
+
+ // Called after calculating base experience gain.
+ virtual void OnBaseGainCalculation(uint32& /*gain*/, uint8 /*playerLevel*/, uint8 /*mobLevel*/, ContentLevels /*content*/) { }
+
+ // Called after calculating experience gain.
+ virtual void OnGainCalculation(uint32& /*gain*/, Player* /*player*/, Unit* /*unit*/) { }
+
+ // Called when calculating the experience rate for group experience.
+ virtual void OnGroupRateCalculation(float& /*rate*/, uint32 /*count*/, bool /*isRaid*/) { }
+};
+
+template<class TMap> class MapScript : public UpdatableScript<TMap>
+{
+ MapEntry const* _mapEntry;
+
+ protected:
+
+ MapScript(uint32 mapId)
+ : _mapEntry(sMapStore.LookupEntry(mapId))
+ {
+ if (!_mapEntry)
+ sLog->outError("Invalid MapScript for %u; no such map ID.", mapId);
+ }
+
+ public:
+
+ // Gets the MapEntry structure associated with this script. Can return NULL.
+ MapEntry const* GetEntry() { return _mapEntry; }
+
+ // Called when the map is created.
+ virtual void OnCreate(TMap* /*map*/) { }
+
+ // Called just before the map is destroyed.
+ virtual void OnDestroy(TMap* /*map*/) { }
+
+ // Called when a grid map is loaded.
+ virtual void OnLoadGridMap(TMap* /*map*/, GridMap* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { }
+
+ // Called when a grid map is unloaded.
+ virtual void OnUnloadGridMap(TMap* /*map*/, GridMap* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { }
+
+ // Called when a player enters the map.
+ virtual void OnPlayerEnter(TMap* /*map*/, Player* /*player*/) { }
+
+ // Called when a player leaves the map.
+ virtual void OnPlayerLeave(TMap* /*map*/, Player* /*player*/) { }
+
+ // Called on every map update tick.
+ virtual void OnUpdate(TMap* /*map*/, uint32 /*diff*/) { }
+};
+
+class WorldMapScript : public ScriptObject, public MapScript<Map>
+{
+ protected:
+
+ WorldMapScript(const char* name, uint32 mapId);
+};
+
+class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
+{
+ protected:
+
+ InstanceMapScript(const char* name, uint32 mapId);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Gets an InstanceScript object for this instance.
+ virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; }
+};
+
+class BattlegroundMapScript : public ScriptObject, public MapScript<BattlegroundMap>
+{
+ protected:
+
+ BattlegroundMapScript(const char* name, uint32 mapId);
+};
+
+class ItemScript : public ScriptObject
+{
+ protected:
+
+ ItemScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when a player accepts a quest from the item.
+ virtual bool OnQuestAccept(Player* /*player*/, Item* /*item*/, Quest const* /*quest*/) { return false; }
+
+ // Called when a player uses the item.
+ virtual bool OnUse(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/) { return false; }
+
+ // Called when the item expires (is destroyed).
+ virtual bool OnExpire(Player* /*player*/, ItemTemplate const* /*proto*/) { return false; }
+};
+
+class CreatureScript : public ScriptObject, public UpdatableScript<Creature>
+{
+ protected:
+
+ CreatureScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when a player opens a gossip dialog with the creature.
+ virtual bool OnGossipHello(Player* /*player*/, Creature* /*creature*/) { return false; }
+
+ // Called when a player selects a gossip item in the creature's gossip menu.
+ virtual bool OnGossipSelect(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+
+ // Called when a player selects a gossip with a code in the creature's gossip menu.
+ virtual bool OnGossipSelectCode(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
+
+ // Called when a player accepts a quest from the creature.
+ virtual bool OnQuestAccept(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+
+ // Called when a player selects a quest in the creature's quest menu.
+ virtual bool OnQuestSelect(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+
+ // Called when a player completes a quest with the creature.
+ virtual bool OnQuestComplete(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+
+ // Called when a player selects a quest reward.
+ virtual bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+
+ // Called when the dialog status between a player and the creature is requested.
+ virtual uint32 GetDialogStatus(Player* /*player*/, Creature* /*creature*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; }
+
+ // Called when a CreatureAI object is needed for the creature.
+ virtual CreatureAI* GetAI(Creature* /*creature*/) const { return NULL; }
+};
+
+class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
+{
+ protected:
+
+ GameObjectScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when a player opens a gossip dialog with the gameobject.
+ virtual bool OnGossipHello(Player* /*player*/, GameObject* /*go*/) { return false; }
+
+ // Called when a player selects a gossip item in the gameobject's gossip menu.
+ virtual bool OnGossipSelect(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+
+ // Called when a player selects a gossip with a code in the gameobject's gossip menu.
+ virtual bool OnGossipSelectCode(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
+
+ // Called when a player accepts a quest from the gameobject.
+ virtual bool OnQuestAccept(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/) { return false; }
+
+ // Called when a player selects a quest reward.
+ virtual bool OnQuestReward(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+
+ // Called when the dialog status between a player and the gameobject is requested.
+ virtual uint32 GetDialogStatus(Player* /*player*/, GameObject* /*go*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; }
+
+ // Called when the game object is destroyed (destructible buildings only).
+ virtual void OnDestroyed(GameObject* /*go*/, Player* /*player*/) { }
+
+ // Called when the game object is damaged (destructible buildings only).
+ virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/) { }
+
+ // Called when the game object loot state is changed.
+ virtual void OnLootStateChanged(GameObject* /*go*/, uint32 /*state*/, Unit* /*unit*/) { }
+
+ // Called when the game object state is changed.
+ virtual void OnGameObjectStateChanged(GameObject* /*go*/, uint32 /*state*/) { }
+
+ // Called when a GameObjectAI object is needed for the gameobject.
+ virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; }
+};
+
+class AreaTriggerScript : public ScriptObject
+{
+ protected:
+
+ AreaTriggerScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when the area trigger is activated by a player.
+ virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) { return false; }
+};
+
+class BattlegroundScript : public ScriptObject
+{
+ protected:
+
+ BattlegroundScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Should return a fully valid Battleground object for the type ID.
+ virtual Battleground* GetBattleground() const = 0;
+};
+
+class OutdoorPvPScript : public ScriptObject
+{
+ protected:
+
+ OutdoorPvPScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Should return a fully valid OutdoorPvP object for the type ID.
+ virtual OutdoorPvP* GetOutdoorPvP() const = 0;
+};
+
+class CommandScript : public ScriptObject
+{
+ protected:
+
+ CommandScript(const char* name);
+
+ public:
+
+ // Should return a pointer to a valid command table (ChatCommand array) to be used by ChatHandler.
+ virtual ChatCommand* GetCommands() const = 0;
+};
+
+class WeatherScript : public ScriptObject, public UpdatableScript<Weather>
+{
+ protected:
+
+ WeatherScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when the weather changes in the zone this script is associated with.
+ virtual void OnChange(Weather* /*weather*/, WeatherState /*state*/, float /*grade*/) { }
+};
+
+class AuctionHouseScript : public ScriptObject
+{
+ protected:
+
+ AuctionHouseScript(const char* name);
+
+ public:
+
+ // Called when an auction is added to an auction house.
+ virtual void OnAuctionAdd(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { }
+
+ // Called when an auction is removed from an auction house.
+ virtual void OnAuctionRemove(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { }
+
+ // Called when an auction was succesfully completed.
+ virtual void OnAuctionSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { }
+
+ // Called when an auction expires.
+ virtual void OnAuctionExpire(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { }
+};
+
+class ConditionScript : public ScriptObject
+{
+ protected:
+
+ ConditionScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when a single condition is checked for a player.
+ virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
+};
+
+class VehicleScript : public ScriptObject
+{
+ protected:
+
+ VehicleScript(const char* name);
+
+ public:
+
+ // Called after a vehicle is installed.
+ virtual void OnInstall(Vehicle* /*veh*/) { }
+
+ // Called after a vehicle is uninstalled.
+ virtual void OnUninstall(Vehicle* /*veh*/) { }
+
+ // Called when a vehicle resets.
+ virtual void OnReset(Vehicle* /*veh*/) { }
+
+ // Called after an accessory is installed in a vehicle.
+ virtual void OnInstallAccessory(Vehicle* /*veh*/, Creature* /*accessory*/) { }
+
+ // Called after a passenger is added to a vehicle.
+ virtual void OnAddPassenger(Vehicle* /*veh*/, Unit* /*passenger*/, int8 /*seatId*/) { }
+
+ // Called after a passenger is removed from a vehicle.
+ virtual void OnRemovePassenger(Vehicle* /*veh*/, Unit* /*passenger*/) { }
+};
+
+class DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject>
+{
+ protected:
+
+ DynamicObjectScript(const char* name);
+};
+
+class TransportScript : public ScriptObject, public UpdatableScript<Transport>
+{
+ protected:
+
+ TransportScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when a player boards the transport.
+ virtual void OnAddPassenger(Transport* /*transport*/, Player* /*player*/) { }
+
+ // Called when a creature boards the transport.
+ virtual void OnAddCreaturePassenger(Transport* /*transport*/, Creature* /*creature*/) { }
+
+ // Called when a player exits the transport.
+ virtual void OnRemovePassenger(Transport* /*transport*/, Player* /*player*/) { }
+
+ // Called when a transport moves.
+ virtual void OnRelocate(Transport* /*transport*/, uint32 /*waypointId*/, uint32 /*mapId*/, float /*x*/, float /*y*/, float /*z*/) { }
+};
+
+class AchievementCriteriaScript : public ScriptObject
+{
+ protected:
+
+ AchievementCriteriaScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return true; }
+
+ // Called when an additional criteria is checked.
+ virtual bool OnCheck(Player* source, Unit* target) = 0;
+};
+
+class PlayerScript : public ScriptObject
+{
+ protected:
+
+ PlayerScript(const char* name);
+
+ public:
+
+ // Called when a player kills another player
+ virtual void OnPVPKill(Player* /*killer*/, Player* /*killed*/) { }
+
+ // Called when a player kills a creature
+ virtual void OnCreatureKill(Player* /*killer*/, Creature* /*killed*/) { }
+
+ // Called when a player is killed by a creature
+ virtual void OnPlayerKilledByCreature(Creature* /*killer*/, Player* /*killed*/) { }
+
+ // Called when a player's level changes (right before the level is applied)
+ virtual void OnLevelChanged(Player* /*player*/, uint8 /*newLevel*/) { }
+
+ // Called when a player's free talent points change (right before the change is applied)
+ virtual void OnFreeTalentPointsChanged(Player* /*player*/, uint32 /*points*/) { }
+
+ // Called when a player's talent points are reset (right before the reset is done)
+ virtual void OnTalentsReset(Player* /*player*/, bool /*noCost*/) { }
+
+ // Called when a player's money is modified (before the modification is done)
+ virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
+
+ // Called when a player gains XP (before anything is given)
+ virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
+
+ // Called when a player's reputation changes (before it is actually changed)
+ virtual void OnReputationChange(Player* /*player*/, uint32 /*factionId*/, int32& /*standing*/, bool /*incremental*/) { }
+
+ // Called when a duel is requested
+ virtual void OnDuelRequest(Player* /*target*/, Player* /*challenger*/) { }
+
+ // Called when a duel starts (after 3s countdown)
+ virtual void OnDuelStart(Player* /*player1*/, Player* /*player2*/) { }
+
+ // Called when a duel ends
+ virtual void OnDuelEnd(Player* /*winner*/, Player* /*loser*/, DuelCompleteType /*type*/) { }
+
+ // Both of the below are called on emote opcodes.
+ virtual void OnEmote(Player* /*player*/, uint32 /*emote*/) { }
+
+ virtual void OnTextEmote(Player* /*player*/, uint32 /*textEmote*/, uint32 /*emoteNum*/, uint64 /*guid*/) { }
+
+ // Called in Spell::Cast.
+ virtual void OnSpellCast(Player* /*player*/, Spell* /*spell*/, bool /*skipCheck*/) { }
+
+ // Called when a player logs in.
+ virtual void OnLogin(Player* /*player*/) { }
+
+ // Called when a player logs out.
+ virtual void OnLogout(Player* /*player*/) { }
+
+ // Called when a player is created.
+ virtual void OnCreate(Player* /*player*/) { }
+
+ // Called when a player is deleted.
+ virtual void OnDelete(uint64 /*guid*/) { }
+
+ // Called when a player is bound to an instance
+ virtual void OnBindToInstance(Player* /*player*/, Difficulty /*difficulty*/, uint32 /*mapId*/, bool /*permanent*/) { }
+
+ // Called when a player switches to a new zone
+ virtual void OnUpdateZone(Player* /*player*/, uint32 /*newZone*/, uint32 /*newArea*/) { }
+
+ // Called when a player changes to a new map (after moving to new map)
+ virtual void OnMapChanged(Player* /*player*/) { }
+};
+
+class GuildScript : public ScriptObject
+{
+ protected:
+
+ GuildScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ // Called when a member is added to the guild.
+ virtual void OnAddMember(Guild* /*guild*/, Player* /*player*/, uint8& /*plRank*/) { }
+
+ // Called when a member is removed from the guild.
+ virtual void OnRemoveMember(Guild* /*guild*/, Player* /*player*/, bool /*isDisbanding*/, bool /*isKicked*/) { }
+
+ // Called when the guild MOTD (message of the day) changes.
+ virtual void OnMOTDChanged(Guild* /*guild*/, const std::string& /*newMotd*/) { }
+
+ // Called when the guild info is altered.
+ virtual void OnInfoChanged(Guild* /*guild*/, const std::string& /*newInfo*/) { }
+
+ // Called when a guild is created.
+ virtual void OnCreate(Guild* /*guild*/, Player* /*leader*/, const std::string& /*name*/) { }
+
+ // Called when a guild is disbanded.
+ virtual void OnDisband(Guild* /*guild*/) { }
+
+ // Called when a guild member withdraws money from a guild bank.
+ virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/, bool /*isRepair*/) { }
+
+ // Called when a guild member deposits money in a guild bank.
+ virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/) { }
+
+ // Called when a guild member moves an item in a guild bank.
+ virtual void OnItemMove(Guild* /*guild*/, Player* /*player*/, Item* /*pItem*/, bool /*isSrcBank*/, uint8 /*srcContainer*/, uint8 /*srcSlotId*/,
+ bool /*isDestBank*/, uint8 /*destContainer*/, uint8 /*destSlotId*/) { }
+
+ virtual void OnEvent(Guild* /*guild*/, uint8 /*eventType*/, uint32 /*playerGuid1*/, uint32 /*playerGuid2*/, uint8 /*newRank*/) { }
+
+ virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, uint32 /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
+};
+
+class GroupScript : public ScriptObject
+{
+ protected:
+
+ GroupScript(const char* name);
+
+ public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ // Called when a member is added to a group.
+ virtual void OnAddMember(Group* /*group*/, uint64 /*guid*/) { }
+
+ // Called when a member is invited to join a group.
+ virtual void OnInviteMember(Group* /*group*/, uint64 /*guid*/) { }
+
+ // Called when a member is removed from a group.
+ virtual void OnRemoveMember(Group* /*group*/, uint64 /*guid*/, RemoveMethod /*method*/, uint64 /*kicker*/, const char* /*reason*/) { }
+
+ // Called when the leader of a group is changed.
+ virtual void OnChangeLeader(Group* /*group*/, uint64 /*newLeaderGuid*/, uint64 /*oldLeaderGuid*/) { }
+
+ // Called when a group is disbanded.
+ virtual void OnDisband(Group* /*group*/) { }
+};
+
+// Placed here due to ScriptRegistry::AddScript dependency.
+#define sScriptMgr ACE_Singleton<ScriptMgr, ACE_Null_Mutex>::instance()
+
+// Manages registration, loading, and execution of scripts.
+class ScriptMgr
+{
+ friend class ACE_Singleton<ScriptMgr, ACE_Null_Mutex>;
+ friend class ScriptObject;
+
+ private:
+
+ ScriptMgr();
+ virtual ~ScriptMgr();
+
+ public: /* Initialization */
+
+ void Initialize();
+ void LoadDatabase();
+ void FillSpellSummary();
+
+ const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; }
+
+ void IncrementScriptCount() { ++_scriptCount; }
+ uint32 GetScriptCount() const { return _scriptCount; }
+
+ public: /* Unloading */
+
+ void Unload();
+
+ public: /* SpellScriptLoader */
+
+ void CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector);
+ void CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector);
+ void CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, std::multimap<uint32, uint32>::iterator> >& scriptVector);
+
+ public: /* ServerScript */
+
+ void OnNetworkStart();
+ void OnNetworkStop();
+ void OnSocketOpen(WorldSocket* socket);
+ void OnSocketClose(WorldSocket* socket, bool wasNew);
+
+ public: /* WorldScript */
+
+ void OnOpenStateChange(bool open);
+ void OnConfigLoad(bool reload);
+ void OnMotdChange(std::string& newMotd);
+ void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask);
+ void OnShutdownCancel();
+ void OnWorldUpdate(uint32 diff);
+ void OnStartup();
+ void OnShutdown();
+
+ public: /* FormulaScript */
+
+ void OnHonorCalculation(float& honor, uint8 level, float multiplier);
+ void OnGrayLevelCalculation(uint8& grayLevel, uint8 playerLevel);
+ void OnColorCodeCalculation(XPColorChar& color, uint8 playerLevel, uint8 mobLevel);
+ void OnZeroDifferenceCalculation(uint8& diff, uint8 playerLevel);
+ void OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content);
+ void OnGainCalculation(uint32& gain, Player* player, Unit* unit);
+ void OnGroupRateCalculation(float& rate, uint32 count, bool isRaid);
+
+ public: /* MapScript */
+
+ void OnCreateMap(Map* map);
+ void OnDestroyMap(Map* map);
+ void OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy);
+ void OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy);
+ void OnPlayerEnterMap(Map* map, Player* player);
+ void OnPlayerLeaveMap(Map* map, Player* player);
+ void OnMapUpdate(Map* map, uint32 diff);
+
+ public: /* InstanceMapScript */
+
+ InstanceScript* CreateInstanceScript(InstanceMap* map);
+
+ public: /* ItemScript */
+
+ bool OnQuestAccept(Player* player, Item* item, Quest const* quest);
+ bool OnItemUse(Player* player, Item* item, SpellCastTargets const& targets);
+ bool OnItemExpire(Player* player, ItemTemplate const* proto);
+
+ public: /* CreatureScript */
+
+ bool OnGossipHello(Player* player, Creature* creature);
+ bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action);
+ bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code);
+ bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest);
+ bool OnQuestSelect(Player* player, Creature* creature, Quest const* quest);
+ bool OnQuestComplete(Player* player, Creature* creature, Quest const* quest);
+ bool OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt);
+ uint32 GetDialogStatus(Player* player, Creature* creature);
+ CreatureAI* GetCreatureAI(Creature* creature);
+ void OnCreatureUpdate(Creature* creature, uint32 diff);
+
+ public: /* GameObjectScript */
+
+ bool OnGossipHello(Player* player, GameObject* go);
+ bool OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action);
+ bool OnGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code);
+ bool OnQuestAccept(Player* player, GameObject* go, Quest const* quest);
+ bool OnQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt);
+ uint32 GetDialogStatus(Player* player, GameObject* go);
+ void OnGameObjectDestroyed(GameObject* go, Player* player);
+ void OnGameObjectDamaged(GameObject* go, Player* player);
+ void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit);
+ void OnGameObjectStateChanged(GameObject* go, uint32 state);
+ void OnGameObjectUpdate(GameObject* go, uint32 diff);
+ GameObjectAI* GetGameObjectAI(GameObject* go);
+
+ public: /* AreaTriggerScript */
+
+ bool OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger);
+
+ public: /* BattlegroundScript */
+
+ Battleground* CreateBattleground(BattlegroundTypeId typeId);
+
+ public: /* OutdoorPvPScript */
+
+ OutdoorPvP* CreateOutdoorPvP(OutdoorPvPData const* data);
+
+ public: /* CommandScript */
+
+ std::vector<ChatCommand*> GetChatCommands();
+
+ public: /* WeatherScript */
+
+ void OnWeatherChange(Weather* weather, WeatherState state, float grade);
+ void OnWeatherUpdate(Weather* weather, uint32 diff);
+
+ public: /* AuctionHouseScript */
+
+ void OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry);
+ void OnAuctionRemove(AuctionHouseObject* ah, AuctionEntry* entry);
+ void OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry);
+ void OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry);
+
+ public: /* ConditionScript */
+
+ bool OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo);
+
+ public: /* VehicleScript */
+
+ void OnInstall(Vehicle* veh);
+ void OnUninstall(Vehicle* veh);
+ void OnReset(Vehicle* veh);
+ void OnInstallAccessory(Vehicle* veh, Creature* accessory);
+ void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId);
+ void OnRemovePassenger(Vehicle* veh, Unit* passenger);
+
+ public: /* DynamicObjectScript */
+
+ void OnDynamicObjectUpdate(DynamicObject* dynobj, uint32 diff);
+
+ public: /* TransportScript */
+
+ void OnAddPassenger(Transport* transport, Player* player);
+ void OnAddCreaturePassenger(Transport* transport, Creature* creature);
+ void OnRemovePassenger(Transport* transport, Player* player);
+ void OnTransportUpdate(Transport* transport, uint32 diff);
+ void OnRelocate(Transport* transport, uint32 waypointId, uint32 mapId, float x, float y, float z);
+
+ public: /* AchievementCriteriaScript */
+
+ bool OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target);
+
+ public: /* PlayerScript */
+
+ void OnPVPKill(Player* killer, Player* killed);
+ void OnCreatureKill(Player* killer, Creature* killed);
+ void OnPlayerKilledByCreature(Creature* killer, Player* killed);
+ void OnPlayerLevelChanged(Player* player, uint8 oldLevel);
+ void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints);
+ void OnPlayerTalentsReset(Player* player, bool noCost);
+ void OnPlayerMoneyChanged(Player* player, int32& amount);
+ void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
+ void OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
+ void OnPlayerDuelRequest(Player* target, Player* challenger);
+ void OnPlayerDuelStart(Player* player1, Player* player2);
+ void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type);
+ void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg);
+ void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver);
+ void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group);
+ void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild);
+ void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel);
+ void OnPlayerEmote(Player* player, uint32 emote);
+ void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, uint64 guid);
+ void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck);
+ void OnPlayerLogin(Player* player);
+ void OnPlayerLogout(Player* player);
+ void OnPlayerCreate(Player* player);
+ void OnPlayerDelete(uint64 guid);
+ void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent);
+ void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea);
+
+ public: /* GuildScript */
+
+ void OnGuildAddMember(Guild* guild, Player* player, uint8& plRank);
+ void OnGuildRemoveMember(Guild* guild, Player* player, bool isDisbanding, bool isKicked);
+ void OnGuildMOTDChanged(Guild* guild, const std::string& newMotd);
+ void OnGuildInfoChanged(Guild* guild, const std::string& newInfo);
+ void OnGuildCreate(Guild* guild, Player* leader, const std::string& name);
+ void OnGuildDisband(Guild* guild);
+ void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair);
+ void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount);
+ void OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
+ bool isDestBank, uint8 destContainer, uint8 destSlotId);
+ void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
+ void OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId);
+
+ public: /* GroupScript */
+
+ void OnGroupAddMember(Group* group, uint64 guid);
+ void OnGroupInviteMember(Group* group, uint64 guid);
+ void OnGroupRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, const char* reason);
+ void OnGroupChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid);
+ void OnGroupDisband(Group* group);
+
+ public: /* Scheduled scripts */
+
+ uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
+ uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; }
+ uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; }
+ bool IsScriptScheduled() const { return _scheduledScripts > 0; }
+
+ private:
+
+ uint32 _scriptCount;
+
+ //atomic op counter for active scripts amount
+ ACE_Atomic_Op<ACE_Thread_Mutex, long> _scheduledScripts;
+};
+
+template<class TScript>
+class ScriptRegistry
+{
+ public:
+
+ typedef std::map<uint32, TScript*> ScriptMap;
+ typedef typename ScriptMap::iterator ScriptMapIterator;
+
+ // The actual list of scripts. This will be accessed concurrently, so it must not be modified
+ // after server startup.
+ static ScriptMap ScriptPointerList;
+
+ static void AddScript(TScript* const script)
+ {
+ ASSERT(script);
+
+ // See if the script is using the same memory as another script. If this happens, it means that
+ // someone forgot to allocate new memory for a script.
+ for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
+ {
+ if (it->second == script)
+ {
+ sLog->outError("Script '%s' has same memory pointer as '%s'.",
+ script->GetName().c_str(), it->second->GetName().c_str());
+
+ return;
+ }
+ }
+
+ if (script->IsDatabaseBound())
+ {
+ // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
+ // through a script name (or similar).
+ uint32 id = sObjectMgr->GetScriptId(script->GetName().c_str());
+ if (id)
+ {
+ // Try to find an existing script.
+ bool existing = false;
+ for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
+ {
+ // If the script names match...
+ if (it->second->GetName() == script->GetName())
+ {
+ // ... It exists.
+ existing = true;
+ break;
+ }
+ }
+
+ // If the script isn't assigned -> assign it!
+ if (!existing)
+ {
+ ScriptPointerList[id] = script;
+ sScriptMgr->IncrementScriptCount();
+ }
+ else
+ {
+ // If the script is already assigned -> delete it!
+ sLog->outError("Script '%s' already assigned with the same script name, so the script can't work.",
+ script->GetName().c_str());
+
+ ASSERT(false); // Error that should be fixed ASAP.
+ }
+ }
+ else
+ {
+ // The script uses a script name from database, but isn't assigned to anything.
+ if (script->GetName().find("Smart") == std::string::npos)
+ sLog->outErrorDb("Script named '%s' does not have a script name assigned in database.",
+ script->GetName().c_str());
+ }
+ }
+ else
+ {
+ // We're dealing with a code-only script; just add it.
+ ScriptPointerList[_scriptIdCounter++] = script;
+ sScriptMgr->IncrementScriptCount();
+ }
+ }
+
+ // Gets a script by its ID (assigned by ObjectMgr).
+ static TScript* GetScriptById(uint32 id)
+ {
+ ScriptMapIterator it = ScriptPointerList.find(id);
+ if (it != ScriptPointerList.end())
+ return it->second;
+
+ return NULL;
+ }
+
+ private:
+
+ // Counter used for code-only scripts.
+ static uint32 _scriptIdCounter;
+};
+
+#endif