/*
* Copyright (C) 2005-2009 MaNGOS
*
* Copyright (C) 2008-2010 Trinity
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SC_SCRIPTMGR_H
#define SC_SCRIPTMGR_H
#include "Common.h"
#include "CompilerDefs.h"
#include "DBCStructure.h"
#include "Config.h"
#include "ObjectMgr.h"
#include "Battleground.h"
#include "OutdoorPvPMgr.h"
#include "SharedDefines.h"
#include "Chat.h"
#include "Weather.h"
#include "AuctionHouseMgr.h"
#include "ConditionMgr.h"
#include "Vehicle.h"
#include "Transport.h"
#include "AchievementMgr.h"
class Player;
class Creature;
class CreatureAI;
class InstanceScript;
class SpellScript;
class Quest;
class Item;
class GameObject;
class SpellCastTargets;
class Map;
class Unit;
class WorldObject;
struct ItemPrototype;
class Spell;
class ScriptMgr;
class WorldSocket;
#define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid)
#define DEFAULT_TEXT ""
// Generic scripting text function.
void DoScriptText(int32 textEntry, WorldObject* pSource, Unit *pTarget = NULL);
/*
TODO: Add more script type classes.
ChatScript
MailScript
SessionScript
CollisionScript
GroupScript
ArenaTeamScript
GuildScript
*/
/*
Standard procedure when adding new script type classes:
First of all, define the actual class, and have it inherit from ScriptObject, like so:
class MyScriptType : public ScriptObject
{
uint32 _someId;
private:
void RegisterSelf();
protected:
MyScriptType(const char* name, uint32 someId)
: ScriptObject(name), _someId(someId)
{
ScriptMgr::ScriptRegistry::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 ScriptMgr::ScriptRegistry;
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 UpdatableScript
{
protected:
UpdatableScript()
{
}
public:
virtual void OnUpdate(TObject* obj, uint32 diff) { }
};
class SpellHandlerScript : public ScriptObject
{
protected:
SpellHandlerScript(const char* name);
public:
bool IsDatabaseBound() const { return true; }
// Should return a fully valid SpellScript pointer.
virtual SpellScript* GetSpellScript() const = 0;
};
class AuraHandlerScript : public ScriptObject
{
protected:
AuraHandlerScript(const char* name);
public:
bool IsDatabaseBound() const { return true; }
// Should return a fully valid AuraScript pointer.
// virtual AuraScript* GetAuraScript() const = 0;
};
class ServerScript : public ScriptObject
{
protected:
ServerScript(const char* name);
public:
// Called when reactive socket I/O is started (WorldSocketMgr).
virtual void OnNetworkStart() { }
// Called when reactive I/O is stopped.
virtual void OnNetworkStop() { }
// Called when a remote socket establishes a connection to the server. Do not store the socket object.
virtual void OnSocketOpen(WorldSocket* socket) { }
// Called when a socket is closed. Do not store the socket object, and do not rely on the connection
// being open; it is not.
virtual void OnSocketClose(WorldSocket* socket, bool wasNew) { }
// Called when a packet is sent to a client. The packet object is a copy of the original packet, so reading
// and modifying it is safe.
virtual void OnPacketSend(WorldSocket* socket, WorldPacket& packet) { }
// Called when a (valid) packet is received by a client. The packet object is a copy of the original packet, so
// reading and modifying it is safe.
virtual void OnPacketReceive(WorldSocket* socket, WorldPacket& packet) { }
// Called when an invalid (unknown opcode) packet is received by a client. The packet is a reference to the orignal
// packet; not a copy. This allows you to actually handle unknown packets (for whatever purpose).
virtual void OnUnknownPacketReceive(WorldSocket* socket, WorldPacket& packet) { }
};
class WorldScript : public ScriptObject, public UpdatableScript
{
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(void* null, 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, uint32 count) { }
// Called after calculating honor.
virtual void OnHonorCalculation(uint32& honor, uint8 level, uint32 count) { }
// 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 MapScript : public UpdatableScript
{
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