aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/world_database.sql14
-rw-r--r--sql/updates/9012_world_spell_script_names.sql6
-rw-r--r--src/server/game/CMakeLists.txt1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp109
-rw-r--r--src/server/game/Globals/ObjectMgr.h8
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h16
-rw-r--r--src/server/game/PrecompiledHeaders/ScriptPCH.h1
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp27
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp22
-rw-r--r--src/server/game/Scripting/ScriptMgr.h9
-rw-r--r--src/server/game/Spells/Spell.cpp40
-rw-r--r--src/server/game/Spells/Spell.h8
-rw-r--r--src/server/game/Spells/SpellScript.cpp215
-rw-r--r--src/server/game/Spells/SpellScript.h154
-rw-r--r--src/server/game/World/World.cpp6
-rw-r--r--src/server/scripts/Examples/example_spell.cpp101
-rw-r--r--src/server/scripts/World/spell_dk.cpp36
-rw-r--r--src/server/scripts/World/spell_druid.cpp36
-rw-r--r--src/server/scripts/World/spell_generic.cpp37
-rw-r--r--src/server/scripts/World/spell_hunter.cpp36
-rw-r--r--src/server/scripts/World/spell_mage.cpp36
-rw-r--r--src/server/scripts/World/spell_paladin.cpp36
-rw-r--r--src/server/scripts/World/spell_pri.cpp34
-rw-r--r--src/server/scripts/World/spell_priest.cpp36
-rw-r--r--src/server/scripts/World/spell_rogue.cpp36
-rw-r--r--src/server/scripts/World/spell_shaman.cpp36
-rw-r--r--src/server/scripts/World/spell_warlock.cpp36
-rw-r--r--src/server/scripts/World/spell_warrior.cpp36
-rw-r--r--src/server/shared/Utilities/Util.h23
-rw-r--r--win/VC90/game.vcproj76
30 files changed, 1253 insertions, 14 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql
index 8b5f03706a8..03ce3ba57f2 100644
--- a/sql/base/world_database.sql
+++ b/sql/base/world_database.sql
@@ -14570,6 +14570,20 @@ INSERT INTO `spelldifficulty_dbc` VALUES
UNLOCK TABLES;
--
+-- Table structure for table `spell_script_names`
+--
+
+DROP TABLE IF EXISTS `spell_script_names`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `spell_script_names` (
+ `spell_id` mediumint(8) NOT NULL,
+ `ScriptName` char(64) NOT NULL,
+ UNIQUE (`spell_id`, `ScriptName`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
-- Table structure for table `transports`
--
diff --git a/sql/updates/9012_world_spell_script_names.sql b/sql/updates/9012_world_spell_script_names.sql
new file mode 100644
index 00000000000..410357f82f9
--- /dev/null
+++ b/sql/updates/9012_world_spell_script_names.sql
@@ -0,0 +1,6 @@
+DROP TABLE IF EXISTS `spell_script_names`;
+CREATE TABLE `spell_script_names` (
+ `spell_id` int(11) NOT NULL,
+ `ScriptName` char(64) NOT NULL,
+ UNIQUE (`spell_id`, `ScriptName`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 40fc77ff464..5738d7b8fc7 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -172,6 +172,7 @@ set(game_STAT_SRCS
Spells/SpellEffects.cpp
Spells/Spell.cpp
Spells/SpellMgr.cpp
+ Spells/SpellScript.cpp
Tools/CharacterDatabaseCleaner.cpp
Tools/PlayerDump.cpp
Tools/Tools.cpp
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 87f8202ddcc..31e6c0c0c72 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -46,6 +46,8 @@
#include "Vehicle.h"
#include "AchievementMgr.h"
#include "DisableMgr.h"
+#include "ScriptMgr.h"
+#include "SpellScript.h"
ScriptMapMap sQuestEndScripts;
ScriptMapMap sQuestStartScripts;
@@ -4893,6 +4895,106 @@ void ObjectMgr::LoadWaypointScripts()
}
}
+void ObjectMgr::LoadSpellScriptNames()
+{
+ mSpellScripts.clear(); // need for reload case
+ QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spell_id, ScriptName FROM spell_script_names");
+
+ uint32 count = 0;
+
+ if (!result)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u spell script names", count);
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ ++count;
+ bar.step();
+
+ Field *fields = result->Fetch();
+
+ int32 spellId = fields[0].GetInt32();
+ const char *scriptName = fields[1].GetString();
+
+ bool allRanks = false;
+ if (spellId <=0)
+ {
+ allRanks = true;
+ spellId = -spellId;
+ }
+
+ SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId);
+ if (!spellEntry)
+ {
+ sLog.outErrorDb("Scriptname:`%s` spell (spell_id:%d) does not exist in `Spell.dbc`.",scriptName,fields[0].GetInt32());
+ continue;
+ }
+
+ if (allRanks)
+ {
+ if (spellmgr.GetFirstSpellInChain(spellId) != spellId)
+ {
+ sLog.outErrorDb("Scriptname:`%s` spell (spell_id:%d) is not first rank of spell.",scriptName,fields[0].GetInt32());
+ continue;
+ }
+ while(spellId)
+ {
+ mSpellScripts.insert(SpellScriptsMap::value_type(spellId, GetScriptId(scriptName)));
+ spellId = spellmgr.GetNextSpellInChain(spellId);
+ }
+ }
+ else
+ mSpellScripts.insert(SpellScriptsMap::value_type(spellId, GetScriptId(scriptName)));
+
+ } while (result->NextRow());
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u spell script names", count);
+}
+
+void ObjectMgr::ValidateSpellScripts()
+{
+ if (mSpellScripts.empty())
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString();
+ sLog.outString(">> Validation done");
+ return;
+ }
+
+ barGoLink bar(mSpellScripts.size());
+ for (SpellScriptsMap::iterator itr = mSpellScripts.begin(); itr != mSpellScripts.end();)
+ {
+ SpellEntry const * spellEntry = sSpellStore.LookupEntry(itr->first);
+ std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > spellScripts;
+ sScriptMgr.CreateSpellScripts(itr->first, spellScripts);
+ SpellScriptsMap::iterator bitr;
+ itr = mSpellScripts.upper_bound(itr->first);
+
+ for (std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> >::iterator sitr = spellScripts.begin(); sitr != spellScripts.end(); ++sitr)
+ {
+ bar.step();
+ sitr->first->Register();
+ if (!sitr->first->_Validate(spellEntry, objmgr.GetScriptName(sitr->second->second)))
+ mSpellScripts.erase(sitr->second);
+ delete sitr->first;
+ }
+ }
+
+ sLog.outString();
+ sLog.outString(">> Validation done");
+}
+
void ObjectMgr::LoadGossipScripts()
{
LoadScripts(sGossipScripts, "gossip_scripts");
@@ -7658,6 +7760,11 @@ uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id)
return 0;
}
+SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id)
+{
+ return SpellScriptsBounds(mSpellScripts.lower_bound(spell_id),mSpellScripts.upper_bound(spell_id));
+}
+
SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
{
switch(pSkill->categoryId)
@@ -8451,6 +8558,8 @@ void ObjectMgr::LoadScriptNames()
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
+ "SELECT DISTINCT(ScriptName) FROM spell_script_names WHERE ScriptName <> '' "
+ "UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
if (!result)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e02fe438c5c..c99a58fe7fb 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -90,6 +90,8 @@ struct ScriptInfo
typedef std::multimap<uint32, ScriptInfo> ScriptMap;
typedef std::map<uint32, ScriptMap > ScriptMapMap;
+typedef std::multimap<uint32, uint32> SpellScriptsMap;
+typedef std::pair<SpellScriptsMap::iterator, SpellScriptsMap::iterator> SpellScriptsBounds;
extern ScriptMapMap sQuestEndScripts;
extern ScriptMapMap sQuestStartScripts;
extern ScriptMapMap sSpellScripts;
@@ -521,6 +523,7 @@ class ObjectMgr
AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const;
uint32 GetAreaTriggerScriptId(uint32 trigger_id);
+ SpellScriptsBounds GetSpellScriptsBounds(uint32 spell_id);
ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const
{
@@ -587,6 +590,9 @@ class ObjectMgr
void LoadGossipScripts();
void LoadWaypointScripts();
+ void LoadSpellScriptNames();
+ void ValidateSpellScripts();
+
bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value);
bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); }
void LoadDbScriptStrings();
@@ -1002,6 +1008,8 @@ class ObjectMgr
SpellClickInfoMap mSpellClickInfoMap;
+ SpellScriptsMap mSpellScripts;
+
ItemRequiredTargetMap m_ItemRequiredTarget;
VehicleAccessoryMap m_VehicleAccessoryMap;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 115e5337e5b..54dfd749b66 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -24,6 +24,17 @@
#include "Define.h"
#include <cassert>
+enum SpellEffIndex
+{
+ EFFECT_0 = 0,
+ EFFECT_1 = 1,
+ EFFECT_2 = 2,
+};
+
+// used in script definitions
+#define EFFECT_FIRST_FOUND 254
+#define EFFECT_ALL 255
+
// loot modes for creatures and gameobjects, bitmask!
enum LootModes
{
@@ -1177,7 +1188,7 @@ enum Targets
TARGET_UNIT_MINIPET = 90,
TARGET_DEST_DEST_RANDOM_DIR_DIST = 91,
TARGET_UNIT_UNK_92 = 92,
- TARGET_CORPSE_AREA_ENEMY_PLAYER_SRC= 93,
+ TARGET_CORPSE_AREA_ENEMY_PLAYER_SRC= 93, // TODO
TARGET_UNIT_VEHICLE = 94,
TARGET_UNIT_DRIVER = 95,
TARGET_UNIT_PASSENGER_0 = 96,
@@ -1190,6 +1201,9 @@ enum Targets
TARGET_UNIT_PASSENGER_7 = 103,
TARGET_UNIT_AREA_PATH = 104,
TARGET_UNIT_UNK_105 = 105, // 1 spell
+ TARGET_DEST_CHANNEL_TARGET = 106, // TODO
+ TARGET_UNK_AREA_UNK_DST_107 = 107, // not enough info - only generic spells avalible
+ TARGET_GAMEOBJECT_AREA_PATH = 108, // TODO
TARGET_DEST_UNK_110 = 110, // some kind of traj?
};
diff --git a/src/server/game/PrecompiledHeaders/ScriptPCH.h b/src/server/game/PrecompiledHeaders/ScriptPCH.h
index f8515e99f89..b716edc3a5b 100644
--- a/src/server/game/PrecompiledHeaders/ScriptPCH.h
+++ b/src/server/game/PrecompiledHeaders/ScriptPCH.h
@@ -22,6 +22,7 @@
#include "DBCStructure.h"
#include "DBCStores.h"
#include "ObjectMgr.h"
+#include "SpellScript.h"
#ifdef _WIN32
#include <windows.h>
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index cf378db2bac..54bd9150a91 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -513,6 +513,20 @@ void AddSC_terokkar_forest();
void AddSC_zangarmarsh();
void AddSC_onevents();
+// spells
+void AddSC_deathknight_spell_scripts();
+void AddSC_druid_spell_scripts();
+void AddSC_generic_spell_scripts();
+void AddSC_hunter_spell_scripts();
+void AddSC_mage_spell_scripts();
+void AddSC_paladin_spell_scripts();
+void AddSC_priest_spell_scripts();
+void AddSC_rogue_spell_scripts();
+void AddSC_shaman_spell_scripts();
+void AddSC_warlock_spell_scripts();
+void AddSC_warrior_spell_scripts();
+void AddSC_example_spell_scripts();
+
#endif
void AddScripts()
@@ -1015,5 +1029,18 @@ void AddScripts()
AddSC_zangarmarsh();
AddSC_onevents();
+ // spells
+ AddSC_deathknight_spell_scripts();
+ AddSC_druid_spell_scripts();
+ AddSC_generic_spell_scripts();
+ AddSC_hunter_spell_scripts();
+ AddSC_mage_spell_scripts();
+ AddSC_paladin_spell_scripts();
+ AddSC_priest_spell_scripts();
+ AddSC_rogue_spell_scripts();
+ AddSC_shaman_spell_scripts();
+ AddSC_warlock_spell_scripts();
+ AddSC_warrior_spell_scripts();
+ AddSC_example_spell_scripts();
#endif
}
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 70b1ff6be64..5f6cce4917d 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -544,3 +544,25 @@ InstanceData* ScriptMgr::CreateInstanceData(Map *map)
return tmpscript->GetInstanceData(map);
}
+void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & script_vector)
+{
+ SpellScriptsBounds bounds = objmgr.GetSpellScriptsBounds(spell_id);
+ for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
+ {
+ Script *tmpscript = m_scripts[itr->second];
+ if (!tmpscript || !tmpscript->GetSpellScript) continue;
+ script_vector.push_back(tmpscript->GetSpellScript());
+ }
+}
+
+void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > & script_vector)
+{
+ SpellScriptsBounds bounds = objmgr.GetSpellScriptsBounds(spell_id);
+ script_vector.reserve(std::distance(bounds.first, bounds.second));
+ for (SpellScriptsMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
+ {
+ Script *tmpscript = m_scripts[itr->second];
+ if (!tmpscript || !tmpscript->GetSpellScript) continue;
+ script_vector.push_back(std::make_pair(tmpscript->GetSpellScript(), itr));
+ }
+}
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index bcb26381809..d477d7a1e39 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -17,6 +17,7 @@ class Player;
class Creature;
class CreatureAI;
class InstanceData;
+class SpellScript;
class Quest;
class Item;
class GameObject;
@@ -25,6 +26,7 @@ class Map;
class Unit;
class WorldObject;
struct ItemPrototype;
+class Spell;
#define MAX_SCRIPTS 5000 //72 bytes each (approx 351kb)
#define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid)
@@ -42,7 +44,7 @@ struct Script
pChooseReward(NULL), pGODestroyed(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL),
pGOQuestAccept(NULL), pGOChooseReward(NULL),pItemUse(NULL), pItemExpire(NULL),
pEffectDummyCreature(NULL), pEffectDummyGameObj(NULL), pEffectDummyItem(NULL),
- GetAI(NULL), GetInstanceData(NULL)
+ GetAI(NULL), GetInstanceData(NULL), GetSpellScript(NULL)
{}
std::string Name;
@@ -89,6 +91,9 @@ struct Script
CreatureAI* (*GetAI)(Creature*);
InstanceData* (*GetInstanceData)(Map*);
+ SpellScript*(*GetSpellScript)();
+ //AuraScript*(*GetAuraScript)();
+
void RegisterSelf();
};
@@ -143,6 +148,8 @@ class ScriptMgr
bool EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget);
bool EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget);
InstanceData* CreateInstanceData(Map *map);
+ void CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & script_vector);
+ void CreateSpellScripts(uint32 spell_id, std::vector<std::pair<SpellScript *, SpellScriptsMap::iterator> > & script_vector);
};
//Config file accessors
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index a53142bf296..eb7c2c9b4fa 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -52,6 +52,7 @@
#include "ScriptMgr.h"
#include "ConditionMgr.h"
#include "DisableMgr.h"
+#include "SpellScript.h"
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
@@ -455,6 +456,14 @@ Spell::Spell(Unit* Caster, SpellEntry const *info, bool triggered, uint64 origin
Spell::~Spell()
{
+ // unload scripts
+ while(!m_loadedScripts.empty())
+ {
+ std::list<SpellScript *>::iterator itr = m_loadedScripts.begin();
+ (*itr)->Unload();
+ delete (*itr);
+ m_loadedScripts.erase(itr);
+ }
if (m_referencedFromCurrentSpell && m_selfContainer && *m_selfContainer == this)
{
// Clean the reference to avoid later crash.
@@ -2748,6 +2757,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
finish(false);
return;
}
+ LoadScripts();
if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
@@ -4479,7 +4489,6 @@ void Spell::HandleThreatSpells(uint32 spellId)
void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i)
{
-
if (!sScriptMgr.OnSpellCast(pUnitTarget,pItemTarget,pGOTarget,i,m_spellInfo))
return;
@@ -4495,12 +4504,21 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
sLog.outDebug("Spell: %u Effect : %u", m_spellInfo->Id, eff);
+ for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ std::list<SpellScript::EffectHandler>::iterator effEndItr = (*scritr)->EffectHandlers.end(), effItr = (*scritr)->EffectHandlers.begin();
+ for(; effItr != effEndItr ; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellInfo, i))
+ (*effItr).Call(*scritr, (SpellEffIndex)i);
+ }
+ }
+
//we do not need DamageMultiplier here.
damage = CalculateDamage(i, NULL);
if (eff < TOTAL_SPELL_EFFECTS)
{
- //sLog.outDebug("WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff);
(this->*SpellEffects[eff])(i);
}
}
@@ -7076,3 +7094,21 @@ void Spell::SelectTrajTargets()
m_targets.setDst(x, y, z, m_caster->GetOrientation());
}
}
+
+void Spell::LoadScripts()
+{
+ sLog.outError("Spell::LoadScripts");
+ sScriptMgr.CreateSpellScripts(m_spellInfo->Id, m_loadedScripts);
+ for(std::list<SpellScript *>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end() ;)
+ {
+ if (!(*itr)->_Load(this))
+ {
+ std::list<SpellScript *>::iterator bitr = itr;
+ ++itr;
+ m_loadedScripts.erase(bitr);
+ continue;
+ }
+ (*itr)->Register();
+ ++itr;
+ }
+}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 563572ec1fd..368add34926 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -29,6 +29,8 @@ class Player;
class GameObject;
class DynamicObject;
class Aura;
+struct SpellEntry;
+class SpellScript;
// These flags represent the inner states of the targeting system
enum SpellInternalTargetFlags
@@ -268,6 +270,7 @@ class Spell
{
friend struct Trinity::SpellNotifierCreatureAndPlayer;
friend void Unit::SetCurrentCastedSpell(Spell * pSpell);
+ friend class SpellScript;
public:
void EffectNULL(uint32);
@@ -506,6 +509,7 @@ class Spell
Unit* GetCaster() const { return m_caster; }
Unit* GetOriginalCaster() const { return m_originalCaster; }
+ SpellEntry const * GetSpellInfo() const { return m_spellInfo; }
int32 GetPowerCost() const { return m_powerCost; }
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
@@ -650,6 +654,10 @@ class Spell
void SpellDamageWeaponDmg(uint32 i);
void SpellDamageHeal(uint32 i);
+ // Scripting system
+ void LoadScripts();
+ std::list<SpellScript *> m_loadedScripts;
+
// effect helpers
void GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0);
void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const *properties);
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
new file mode 100644
index 00000000000..fb2944fa651
--- /dev/null
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * 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
+ */
+
+#include "SpellScript.h"
+#include "Spell.h"
+
+bool _SpellScript::_Validate(SpellEntry const * entry, const char * scriptname)
+{
+ if (!Validate(entry))
+ {
+ sLog.outError("TSCR: Spell `%u` did not pass Validate() function of script `%s` - script will be not added to the spell", entry->Id, scriptname);
+ return false;
+ }
+ return true;
+}
+
+_SpellScript::EffectHook::EffectHook(uint8 _effIndex)
+{
+ // effect index must be in range <0;2>, allow use of special effindexes
+ ASSERT(_effIndex == EFFECT_ALL || _effIndex == EFFECT_FIRST_FOUND || _effIndex < MAX_SPELL_EFFECTS);
+ effIndex = _effIndex;
+}
+
+uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellEntry const * spellEntry)
+{
+ uint8 mask = 0;
+ if ((effIndex == EFFECT_ALL) || (effIndex == EFFECT_FIRST_FOUND))
+ {
+ for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if ((effIndex == EFFECT_FIRST_FOUND) && mask)
+ return mask;
+ if (CheckEffect(spellEntry, effIndex))
+ mask |= (uint8)1<<effIndex;
+ }
+ }
+ else
+ {
+ if (CheckEffect(spellEntry, effIndex))
+ mask |= (uint8)1<<effIndex;
+ }
+ return mask;
+}
+
+bool _SpellScript::EffectHook::IsEffectAffected(SpellEntry const * spellEntry, uint8 effIndex)
+{
+ return GetAffectedEffectsMask(spellEntry) & 1<<effIndex;
+}
+
+std::string _SpellScript::EffectHook::EffIndexToString()
+{
+ switch(effIndex)
+ {
+ case EFFECT_ALL:
+ return "EFFECT_ALL";
+ case EFFECT_FIRST_FOUND:
+ return "EFFECT_FIRST_FOUND";
+ case EFFECT_0:
+ return "EFFECT_0";
+ case EFFECT_1:
+ return "EFFECT_1";
+ case EFFECT_2:
+ return "EFFECT_2";
+ }
+ return "Invalid Value";
+}
+
+bool _SpellScript::EffectNameCheck::Check(SpellEntry const * spellEntry, uint8 effIndex)
+{
+ if (!spellEntry->Effect[effIndex] && !effName)
+ return true;
+ if (!spellEntry->Effect[effIndex])
+ return false;
+ return (effName == SPELL_EFFECT_ANY) || (spellEntry->Effect[effIndex] == effName);
+}
+
+std::string _SpellScript::EffectNameCheck::ToString()
+{
+ switch(effName)
+ {
+ case SPELL_EFFECT_ANY:
+ return "SPELL_EFFECT_ANY";
+ default:
+ char num[10];
+ sprintf (num,"%u",effName);
+ return num;
+ }
+}
+
+bool _SpellScript::EffectAuraNameCheck::Check(SpellEntry const * spellEntry, uint8 effIndex)
+{
+ if (!spellEntry->EffectApplyAuraName[effIndex] && !effAurName)
+ return true;
+ if (!spellEntry->EffectApplyAuraName[effIndex])
+ return false;
+ return (effAurName == SPELL_EFFECT_ANY) || (spellEntry->EffectApplyAuraName[effIndex] == effAurName);
+}
+
+std::string _SpellScript::EffectAuraNameCheck::ToString()
+{
+ switch(effAurName)
+ {
+ case SPELL_AURA_ANY:
+ return "SPELL_AURA_ANY";
+ default:
+ char num[10];
+ sprintf (num,"%u",effAurName);
+ return num;
+ }
+}
+
+SpellScript::EffectHandler::EffectHandler(EffectHandlerFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName)
+ : _SpellScript::EffectNameCheck(_effName), _SpellScript::EffectHook(_effIndex)
+{
+ pEffectHandlerScript = _pEffectHandlerScript;
+}
+
+std::string SpellScript::EffectHandler::ToString()
+{
+ return "Index: " + EffIndexToString() + " Name: " +_SpellScript::EffectNameCheck::ToString();
+}
+
+bool SpellScript::EffectHandler::CheckEffect(SpellEntry const * spellEntry, uint8 effIndex)
+{
+ return _SpellScript::EffectNameCheck::Check(spellEntry, effIndex);
+}
+
+void SpellScript::EffectHandler::Call(SpellScript * spellScript, SpellEffIndex effIndex)
+{
+ (spellScript->*pEffectHandlerScript)(effIndex);
+}
+
+bool SpellScript::_Validate(SpellEntry const * entry, const char * scriptname)
+{
+ for (std::list<EffectHandler>::iterator itr = EffectHandlers.begin(); itr != EffectHandlers.end(); ++itr)
+ {
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ {
+ sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
+ }
+ }
+ return _SpellScript::_Validate(entry, scriptname);
+}
+
+bool SpellScript::_Load(Spell * spell)
+{
+ m_spell = spell;
+ return Load();
+}
+
+Unit * SpellScript::GetCaster()
+{
+ return m_spell->GetCaster();
+}
+
+Unit * SpellScript::GetOriginalCaster()
+{
+ return m_spell->GetOriginalCaster();
+}
+
+SpellEntry const * SpellScript::GetSpellInfo()
+{
+ return m_spell->GetSpellInfo();
+}
+
+Unit * SpellScript::GetEffectUnitTarget()
+{
+ return m_spell->unitTarget;
+}
+
+Creature * SpellScript::GetEffectCreatureTarget()
+{
+ if (m_spell->unitTarget)
+ return m_spell->unitTarget->ToCreature();
+ else
+ return NULL;
+}
+
+Player * SpellScript::GetEffectPlayerTarget()
+{
+ if (m_spell->unitTarget)
+ return m_spell->unitTarget->ToPlayer();
+ else
+ return NULL;
+}
+
+Item * SpellScript::GetEffectItemTarget()
+{
+ return m_spell->itemTarget;
+}
+
+GameObject * SpellScript::GetEffectGOTarget()
+{
+ return m_spell->gameObjTarget;
+}
+
+int32 SpellScript::GetEffectValue()
+{
+ return m_spell->damage;
+}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
new file mode 100644
index 00000000000..73b378db20e
--- /dev/null
+++ b/src/server/game/Spells/SpellScript.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * 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 __SPELL_SCRIPT_H
+#define __SPELL_SCRIPT_H
+
+class Unit;
+struct SpellEntry;
+class SpellScript;
+class Spell;
+
+typedef void(SpellScript::*EffectHandlerFnType)(SpellEffIndex);
+
+#define SPELL_EFFECT_ANY (uint16)-1
+#define SPELL_AURA_ANY (uint16)-1
+
+// helper class from which SpellScript and SpellAura derive, use these classes instead
+class _SpellScript
+{
+ // internal use classes & functions
+ // DO NOT OVERRIDE THESE IN SCRIPTS
+ protected:
+ virtual bool _Validate(SpellEntry const * entry, const char * scriptname);
+ protected:
+ class EffectHook
+ {
+ public:
+ EffectHook(uint8 _effIndex);
+ uint8 GetAffectedEffectsMask(SpellEntry const * spellEntry);
+ bool IsEffectAffected(SpellEntry const * spellEntry, uint8 effIndex);
+ virtual bool CheckEffect(SpellEntry const * spellEntry, uint8 effIndex) = 0;
+ std::string EffIndexToString();
+ protected:
+ uint8 effIndex;
+ };
+ class EffectNameCheck
+ {
+ public:
+ EffectNameCheck(uint16 _effName) {effName = _effName;};
+ bool Check(SpellEntry const * spellEntry, uint8 effIndex);
+ std::string ToString();
+ private:
+ uint16 effName;
+ };
+ class EffectAuraNameCheck
+ {
+ public:
+ EffectAuraNameCheck(uint16 _effAurName) { effAurName = _effAurName; }
+ bool Check(SpellEntry const * spellEntry, uint8 effIndex);
+ std::string ToString();
+ private:
+ uint16 effAurName;
+ };
+ public:
+ //
+ // SpellScript/AuraScript interface base
+ // these functions are safe to override, see notes below for usage instructions
+ //
+ // Function in which handler functions are registered, must be implemented in script
+ virtual void Register() = 0;
+ // Function called on server startup, if returns false script won't be used in core
+ // use for: dbc/template data presence/correctness checks
+ virtual bool Validate(SpellEntry const * spellEntry) {return true;};
+ // Function called when script is created, if returns false script will be unloaded afterwards
+ // use for: initializing local script variables (DO NOT USE CONSTRUCTOR FOR THIS PURPOSE!)
+ virtual bool Load() {return true;};
+ // Function called when script is destroyed
+ // use for: deallocating memory allocated by script
+ virtual void Unload() {};
+};
+
+class SpellScript : public _SpellScript
+{
+ // internal use classes & functions
+ // DO NOT OVERRIDE THESE IN SCRIPTS
+ public:
+ class EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook
+ {
+ public:
+ EffectHandler(EffectHandlerFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName);
+ std::string ToString();
+ bool CheckEffect(SpellEntry const * spellEntry, uint8 effIndex);
+ void Call(SpellScript * spellScript, SpellEffIndex effIndex);
+ private:
+ EffectHandlerFnType pEffectHandlerScript;
+ };
+ public:
+ bool _Validate(SpellEntry const * entry, const char * scriptname);
+ bool _Load(Spell * spell);
+ private:
+ Spell * m_spell;
+ public:
+ //
+ // SpellScript interface
+ // hooks to which you can attach your functions
+ //
+ // List of functions registered by EffectHandlerFn
+ // allows more than one hook
+ // example EffectHandlers += EffectHandlerFn(class::function, EffectIndexSpecifier, EffectNameSpecifier);
+ HookList<EffectHandler> EffectHandlers;
+
+ // methods allowing interaction with Spell object
+ Unit * GetCaster();
+ Unit * GetOriginalCaster();
+ SpellEntry const * GetSpellInfo();
+ // functions useable only during spell hit on target phase
+ Unit * GetEffectUnitTarget();
+ Creature * GetEffectCreatureTarget();
+ Player * GetEffectPlayerTarget();
+ Item * GetEffectItemTarget();
+ GameObject * GetEffectGOTarget();
+ int32 GetEffectValue();
+};
+// SpellScript interface
+//
+// function registering macros, should be used only in Register()
+//
+// EffectHandlerFn
+// called at: Spell hit on unit, just before default effect handler, called for effects matching EffectIndexSpecifier and EffectNameSpecifier conditions
+// hook parameter is current effect index
+// parameters: function to call, EffectIndexSpecifier, EffectNameSpecifier
+#define EffectHandlerFn(F, I, N) EffectHandler((EffectHandlerFnType)&F, I, N)
+
+//
+// definitions:
+//
+// EffectIndexSpecifier - specifies conditions for effects
+// EFFECT_0 - first effect matches
+// EFFECT_1 - second effect matches
+// EFFECT_2 - third effect matches
+// EFFECT_FIRST_FOUND - first effect matching other conditions matches
+// EFFECT_ALL - all effects of spell match
+//
+// EffectNameSpecifier - specifies conditions for spell effect names
+// SPELL_EFFECT_ANY - any effect but not 0 matches condition
+// SPELL_EFFECT_XXX - one of values of enum SpellEffects - effect with equal name matches
+//
+
+#endif // __SPELL_SCRIPT_H
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 5eba5f44182..610a34ee5fe 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1616,9 +1616,15 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading CreatureEventAI Scripts...");
CreatureEAI_Mgr.LoadCreatureEventAI_Scripts();
+ sLog.outString("Loading spell script names...");
+ objmgr.LoadSpellScriptNames();
+
sLog.outString("Initializing Scripts...");
sScriptMgr.ScriptsInit();
+ sLog.outString("Validating spell scripts...");
+ objmgr.ValidateSpellScripts();
+
///- Initialize game time and timers
sLog.outDebug("DEBUG:: Initialize game time and timers");
m_gameTime = time(NULL);
diff --git a/src/server/scripts/Examples/example_spell.cpp b/src/server/scripts/Examples/example_spell.cpp
new file mode 100644
index 00000000000..149cd09d4c9
--- /dev/null
+++ b/src/server/scripts/Examples/example_spell.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * An example of a spell script file
+ * to bind a script to spell you have to add entry for it in `spell_script_names`
+ * where `spell_id` is id of the spell to bind
+ * and `ScriptName` is the name of a script assigned on registration
+ */
+
+#include "ScriptPCH.h"
+
+class spell_ex_49375SpellScript : public SpellScript
+{
+public:
+ std::string localVariable;
+ char * localVariable2;
+private:
+ // effect handler hook - effIndex - effIndex of handled effect of a spell
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ // we're handling SPELL_EFFECT_DUMMY in effIndex 0 here
+ sLog.outError("WE ARE HANDLING DUMMY!");
+ sLog.outError(localVariable.c_str());
+ // make caster cast a spell on a unit target of effect
+ if (Unit * target = GetEffectUnitTarget())
+ GetCaster()->CastSpell(target, 70522, true);
+ };
+ void Register()
+ {
+ // we're registering our function here
+ // function HandleDummy will be called when unit is hit by spell, just before default effect 0 handler
+ EffectHandlers += EffectHandlerFn(spell_ex_49375SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ // this will prompt an error on startup because effect 0 of spell 49375 is set to SPELL_EFFECT_DUMMY, not SPELL_EFFECT_APPLY_AURA
+ //EffectHandlers += EffectHandlerFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ // this will make HandleDummy function to be called on first != 0 effect of spell 49375
+ //EffectHandlers += EffectHandlerFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_FIRST_FOUND, SPELL_EFFECT_ANY);
+ // this will make HandleDummy function to be called on all != 0 effect of spell 49375
+ //EffectHandlers += EffectHandlerFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_ALL, SPELL_EFFECT_ANY);
+ };
+ // function called on server startup
+ // checks if script has data required for it to work
+ bool Validate(SpellEntry const * spellEntry)
+ {
+ // check if spellid 1 exists in dbc
+ if (!sSpellStore.LookupEntry(70522))
+ return false;
+ return true;
+ };
+ // function called just after script is added to spell
+ // we initialize local variables if needed
+ bool Load()
+ {
+ localVariable = "WE'RE USING LOCAL VARIABLE";
+ localVariable2 = new char;
+ return true;
+ // script will be immediately removed from the spell
+ // for example - we don't want this script to be executed on a creature
+ // if (GetCaster()->GetTypeID() != TYPEID_PLAYER)
+ // return false
+ }
+ // function called just before script delete
+ // we free allocated memory
+ void Unload()
+ {
+ delete localVariable2;
+ }
+};
+
+// function which creates SpellScript
+SpellScript * GetSpellScript_spell_ex_49375()
+{
+ return new spell_ex_49375SpellScript();
+}
+
+// this function has to be added to function set in ScriptLoader.cpp
+void AddSC_example_spell_scripts()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ // name to be put in `spell_script_names`
+ newscript->Name = "spell_ex_49375";
+ // assign create function to the script
+ newscript->GetSpellScript = &GetSpellScript_spell_ex_49375;
+ newscript->RegisterSelf();
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_dk.cpp b/src/server/scripts/World/spell_dk.cpp
new file mode 100644
index 00000000000..b8b32d248ff
--- /dev/null
+++ b/src/server/scripts/World/spell_dk.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_DEATHKNIGHT and SPELLFAMILY_GENERIC spells used by deathknight players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_dk_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_deathknight_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_dk_";
+ newscript->GetSpellScript = &GetSpellScript_spell_dk_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_druid.cpp b/src/server/scripts/World/spell_druid.cpp
new file mode 100644
index 00000000000..49f0cae2ade
--- /dev/null
+++ b/src/server/scripts/World/spell_druid.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_DRUID and SPELLFAMILY_GENERIC spells used by druid players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_dru_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_druid_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_dru_";
+ newscript->GetSpellScript = &GetSpellScript_spell_dru_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_generic.cpp b/src/server/scripts/World/spell_generic.cpp
new file mode 100644
index 00000000000..7020d267345
--- /dev/null
+++ b/src/server/scripts/World/spell_generic.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_GENERIC which cannot be included in AI script file
+ * of creature using it or can't be bound to any player class.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_gen_"
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_generic_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_gen_";
+ newscript->GetSpellScript = &GetSpellScript_spell_gen_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_hunter.cpp b/src/server/scripts/World/spell_hunter.cpp
new file mode 100644
index 00000000000..1a3ef010cbb
--- /dev/null
+++ b/src/server/scripts/World/spell_hunter.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_HUNTER, SPELLFAMILY_PET and SPELLFAMILY_GENERIC spells used by hunter players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_hun_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_hunter_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_hun_";
+ newscript->GetSpellScript = &GetSpellScript_spell_hun_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_mage.cpp b/src/server/scripts/World/spell_mage.cpp
new file mode 100644
index 00000000000..4f609800346
--- /dev/null
+++ b/src/server/scripts/World/spell_mage.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_MAGE and SPELLFAMILY_GENERIC spells used by mage players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_mag_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_mage_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_mag_";
+ newscript->GetSpellScript = &GetSpellScript_spell_mag_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_paladin.cpp b/src/server/scripts/World/spell_paladin.cpp
new file mode 100644
index 00000000000..24141205e76
--- /dev/null
+++ b/src/server/scripts/World/spell_paladin.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_SHAMAN and SPELLFAMILY_GENERIC spells used by paladin players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_pal_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_paladin_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_pal_";
+ newscript->GetSpellScript = &GetSpellScript_spell_pal_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_pri.cpp b/src/server/scripts/World/spell_pri.cpp
new file mode 100644
index 00000000000..a659dd8effb
--- /dev/null
+++ b/src/server/scripts/World/spell_pri.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_PRIEST and SPELLFAMILY_GENERIC spells used by warrior players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_pri_".
+ */
+
+void AddSC_mage_spell_scripts()
+{
+ Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_pri_";
+ newscript->GetSpellScript = &GetSpellScript_spell_pri_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_priest.cpp b/src/server/scripts/World/spell_priest.cpp
new file mode 100644
index 00000000000..c5dc3d854ae
--- /dev/null
+++ b/src/server/scripts/World/spell_priest.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_PRIEST and SPELLFAMILY_GENERIC spells used by priest players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_pri_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_priest_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_pri_";
+ newscript->GetSpellScript = &GetSpellScript_spell_pri_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_rogue.cpp b/src/server/scripts/World/spell_rogue.cpp
new file mode 100644
index 00000000000..b701443e98b
--- /dev/null
+++ b/src/server/scripts/World/spell_rogue.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_ROGUE and SPELLFAMILY_GENERIC spells used by rogue players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_rog_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_rogue_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_rog_";
+ newscript->GetSpellScript = &GetSpellScript_spell_rog_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_shaman.cpp b/src/server/scripts/World/spell_shaman.cpp
new file mode 100644
index 00000000000..f689a3c68ee
--- /dev/null
+++ b/src/server/scripts/World/spell_shaman.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_SHAMAN and SPELLFAMILY_GENERIC spells used by shaman players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_sha_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_shaman_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_sha_";
+ newscript->GetSpellScript = &GetSpellScript_spell_sha_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_warlock.cpp b/src/server/scripts/World/spell_warlock.cpp
new file mode 100644
index 00000000000..24ee8d682a2
--- /dev/null
+++ b/src/server/scripts/World/spell_warlock.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_WARLOCK and SPELLFAMILY_GENERIC spells used by warlock players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_warl_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_warlock_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_warl_";
+ newscript->GetSpellScript = &GetSpellScript_spell_warl_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/scripts/World/spell_warrior.cpp b/src/server/scripts/World/spell_warrior.cpp
new file mode 100644
index 00000000000..dbd7901dc09
--- /dev/null
+++ b/src/server/scripts/World/spell_warrior.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_WARRIOR and SPELLFAMILY_GENERIC spells used by warrior players.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_warr_".
+ */
+
+#include "ScriptPCH.h"
+
+void AddSC_warrior_spell_scripts()
+{
+ //Script *newscript;
+
+ /*
+ newscript = new Script;
+ newscript->Name = "spell_warr_";
+ newscript->GetSpellScript = &GetSpellScript_spell_warr_;
+ newscript->RegisterSelf();
+ */
+} \ No newline at end of file
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index 68886bb0d42..bfe1eec5265 100644
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -312,6 +312,29 @@ void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result);
#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF))
#endif
+// simple class for not-modifyable list
+template <typename T>
+class HookList
+{
+ typedef typename std::list<T>::iterator ListIterator;
+ private:
+ typename std::list<T> m_list;
+ public:
+ HookList<T> & operator+=(T t)
+ {
+ m_list.push_back(t);
+ return *this;
+ }
+ ListIterator begin()
+ {
+ return m_list.begin();
+ }
+ ListIterator end()
+ {
+ return m_list.end();
+ }
+};
+
class flag96
{
private:
diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
index f62043c7009..cad732a1500 100644
--- a/win/VC90/game.vcproj
+++ b/win/VC90/game.vcproj
@@ -762,6 +762,50 @@
RelativePath="..\..\src\server\scripts\World\npcs_special.cpp"
>
</File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_dk.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_druid.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_generic.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_hunter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_mage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_paladin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_priest.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_rogue.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_shaman.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_warlock.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\scripts\World\spell_warrior.cpp"
+ >
+ </File>
</Filter>
<Filter
Name="Eastern Kingdoms"
@@ -1646,6 +1690,10 @@
RelativePath="..\..\src\server\scripts\Examples\example_misc.cpp"
>
</File>
+ <File
+ RelativePath="..\..\src\server\scripts\Examples\example_spell.cpp"
+ >
+ </File>
</Filter>
<Filter
Name="Kalimdor"
@@ -4200,16 +4248,16 @@
<File
RelativePath="..\..\src\server\game\Server\Protocol\Handlers\ChannelHandler.cpp"
>
- </File>
- <File
- RelativePath="..\..\src\server\game\Tools\CharacterDatabaseCleaner.cpp"
- >
- </File>
- <File
- RelativePath="..\..\src\server\game\Tools\CharacterDatabaseCleaner.h"
- >
- </File>
- <File
+ </File>
+ <File
+ RelativePath="..\..\src\server\game\Tools\CharacterDatabaseCleaner.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\game\Tools\CharacterDatabaseCleaner.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\server\game\Server\Protocol\Handlers\CharacterHandler.cpp"
>
</File>
@@ -4471,6 +4519,14 @@
RelativePath="..\..\src\server\game\Spells\SpellMgr.h"
>
</File>
+ <File
+ RelativePath="..\..\src\server\game\Spells\SpellScript.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\server\game\Spells\SpellScript.h"
+ >
+ </File>
<Filter
Name="Auras"
>