aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/scripts/world_scripts_full.sql5
-rw-r--r--sql/updates/world/2011_03_04_1_world_spell_script_names.sql8
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h84
-rwxr-xr-xsrc/server/game/Skills/SkillDiscovery.cpp16
-rwxr-xr-xsrc/server/game/Skills/SkillDiscovery.h1
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp32
-rwxr-xr-xsrc/server/game/Spells/Spell.h4
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp2
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp21
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h29
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp34
-rw-r--r--src/server/scripts/Spells/spell_item.cpp34
12 files changed, 262 insertions, 8 deletions
diff --git a/sql/scripts/world_scripts_full.sql b/sql/scripts/world_scripts_full.sql
index e962a3453ec..88c07e6e003 100644
--- a/sql/scripts/world_scripts_full.sql
+++ b/sql/scripts/world_scripts_full.sql
@@ -1847,6 +1847,10 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
( 72706, 'spell_gen_dungeon_credit'),
( 72830, 'spell_gen_dungeon_credit'),
( 72959, 'spell_gen_dungeon_credit'),
+( 60893, 'spell_gen_profession_research'),
+( 61177, 'spell_gen_profession_research'),
+( 61288, 'spell_gen_profession_research'),
+( 61756, 'spell_gen_profession_research'),
-- instances
-- Black Temple
( 41475, 'spell_boss_lady_malande_shield'),
@@ -2103,6 +2107,7 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
( 71905, 'spell_item_shadowmourne'),
( 67533, 'spell_item_red_rider_air_rifle'),
( 26678, 'spell_item_create_heart_candy'),
+( 64323, 'spell_item_book_of_glyph_mastery'),
-- warrior
( 12975, 'spell_warr_last_stand'),
( 59725, 'spell_warr_improved_spell_reflection'),
diff --git a/sql/updates/world/2011_03_04_1_world_spell_script_names.sql b/sql/updates/world/2011_03_04_1_world_spell_script_names.sql
new file mode 100644
index 00000000000..db399ebd042
--- /dev/null
+++ b/sql/updates/world/2011_03_04_1_world_spell_script_names.sql
@@ -0,0 +1,8 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_profession_research';
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_book_of_glyph_mastery';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(60893, 'spell_gen_profession_research'),
+(61177, 'spell_gen_profession_research'),
+(61288, 'spell_gen_profession_research'),
+(61756, 'spell_gen_profession_research'),
+(64323, 'spell_item_book_of_glyph_mastery');
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index fade7de99bf..25011abc64d 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1007,6 +1007,90 @@ enum SpellCastResult
SPELL_CAST_OK = 255 // custom value, don't must be send to client
};
+enum SpellCustomErrors
+{
+ SPELL_CUSTOM_ERROR_NONE = 0,
+ SPELL_CUSTOM_ERROR_CUSTOM_MSG = 1, // Something bad happened, and we want to display a custom message!
+ SPELL_CUSTOM_ERROR_ALEX_BROKE_QUEST = 2, // Alex broke your quest! Thank him later!
+ SPELL_CUSTOM_ERROR_NEED_HELPLESS_VILLAGER = 3, // This spell may only be used on Helpless Wintergarde Villagers that have not been rescued.
+ SPELL_CUSTOM_ERROR_NEED_WARSONG_DISGUISE = 4, // Requires that you be wearing the Warsong Orc Disguise.
+ SPELL_CUSTOM_ERROR_REQUIRES_PLAGUE_WAGON = 5, // You must be closer to a plague wagon in order to drop off your 7th Legion Siege Engineer.
+ SPELL_CUSTOM_ERROR_CANT_TARGET_FRIENDLY_NONPARTY = 6, // You cannot target friendly units outside your party.
+ SPELL_CUSTOM_ERROR_NEED_CHILL_NYMPH = 7, // You must target a weakened chill nymph.
+ SPELL_CUSTOM_ERROR_MUST_BE_IN_ENKILAH = 8, // The Imbued Scourge Shroud will only work when equipped in the Temple City of En'kilah.
+ SPELL_CUSTOM_ERROR_REQUIRES_CORPSE_DUST = 9, // Requires Corpse Dust
+ SPELL_CUSTOM_ERROR_CANT_SUMMON_GARGOYLE = 10, // You cannot summon another gargoyle yet.
+ SPELL_CUSTOM_ERROR_NEED_CORPSE_DUST_IF_NO_TARGET = 11, // Requires Corpse Dust if the target is not dead and humanoid.
+ SPELL_CUSTOM_ERROR_MUST_BE_AT_SHATTERHORN = 12, // Can only be placed near Shatterhorn
+ SPELL_CUSTOM_ERROR_MUST_TARGET_PROTO_DRAKE_EGG = 13, // You must first select a Proto-Drake Egg.
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_TREE = 14, // You must be close to a marked tree.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_TURKEY = 15, // You must target a Fjord Turkey.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_HAWK = 16, // You must target a Fjord Hawk.
+ SPELL_CUSTOM_ERROR_TOO_FAR_FROM_BOUY = 17, // You are too far from the bouy.
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_OIL_SLICK = 18, // Must be used near an oil slick.
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_BOUY = 19, // You must be closer to the buoy!
+ SPELL_CUSTOM_ERROR_WYRMREST_VANQUISHER = 20, // You may only call for the aid of a Wyrmrest Vanquisher in Wyrmrest Temple, The Dragon Wastes, Galakrond's Rest or The Wicked Coil.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_ICE_HEART_JORMUNGAR = 21, // That can only be used on a Ice Heart Jormungar Spawn.
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_SINKHOLE = 22, // You must be closer to a sinkhole to use your map.
+ SPELL_CUSTOM_ERROR_REQUIRES_HAROLD_LANE = 23, // You may only call down a stampede on Harold Lane.
+ SPELL_CUSTOM_ERROR_REQUIRES_GAMMOTH_MAGNATAUR = 24, // You may only use the Pouch of Crushed Bloodspore on Gammothra or other magnataur in the Bloodspore Plains and Gammoth.
+ SPELL_CUSTOM_ERROR_MUST_BE_IN_RESURRECTION_CHAMBER = 25, // Requires the magmawyrm resurrection chamber in the back of the Maw of Neltharion.
+ SPELL_CUSTOM_ERROR_CANT_CALL_WINTERGARDE_HERE = 26, // You may only call down a Wintergarde Gryphon in Wintergarde Keep or the Carrion Fields.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM = 27, // What are you doing? Only aim that thing at Wilhelm!
+ SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH = 28, // Not enough health!
+ SPELL_CUSTOM_ERROR_NO_NEARBY_CORPSES = 29, // There are no nearby corpses to use
+ SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS = 30, // You've created enough ghouls. Return to Gothik the Harvester at Death's Breach.
+ SPELL_CUSTOM_ERROR_GO_FURTHER_FROM_SUNDERED_SHARD = 31, // Your companion does not want to come here. Go further from the Sundered Shard.
+ SPELL_CUSTOM_ERROR_MUST_BE_IN_CAT_FORM = 32, // Must be in Cat Form
+ SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT = 33, // Only Death Knights may enter Ebon Hold.
+ SPELL_CUSTOM_ERROR_MUST_BE_IN_FERAL_FORM = 34, // Must be in Cat Form, Bear Form, or Dire Bear Form
+ SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER = 35, // You must be within range of a Helpless Wintergarde Villager.
+ SPELL_CUSTOM_ERROR_MUST_TARGET_ELEMENTAL_MECHANICAL = 36, // You cannot target an elemental or mechanical corpse.
+ SPELL_CUSTOM_ERROR_MUST_HAVE_USED_DALARAN_CRYSTAL = 37, // This teleport crystal cannot be used until the teleport crystal in Dalaran has been used at least once.
+ SPELL_CUSTOM_ERROR_YOU_ALREADY_HOLD_SOMETHING = 38, // You are already holding something in your hand. You must throw the creature in your hand before picking up another.
+ SPELL_CUSTOM_ERROR_YOU_DONT_HOLD_ANYTHING = 39, // You don't have anything to throw! Find a Vargul and use Gymer Grab to pick one up!
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_VALDURAN = 40, // Bouldercrag's War Horn can only be used within 10 yards of Valduran the Stormborn.
+ SPELL_CUSTOM_ERROR_NO_PASSENGER = 41, // You are not carrying a passenger. There is nobody to drop off.
+ SPELL_CUSTOM_ERROR_CANT_BUILD_MORE_VEHICLES = 42, // You cannot build any more siege vehicles.
+ SPELL_CUSTOM_ERROR_ALREADY_CARRYING_CRUSADER = 43, // You are already carrying a captured Argent Crusader. You must return to the Argent Vanguard infirmary and drop off your passenger before you may pick up another.
+ SPELL_CUSTOM_ERROR_CANT_DO_WHILE_ROOTED = 44, // You can't do that while rooted.
+ SPELL_CUSTOM_ERROR_REQUIRES_NEARBY_TARGET = 45, // Requires a nearby target.
+ SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER = 46, // Nothing left to discover.
+ SPELL_CUSTOM_ERROR_NOT_ENOUGH_TARGETS = 47, // No targets close enough to bluff.
+ SPELL_CUSTOM_ERROR_CONSTRUCT_TOO_FAR = 48, // Your Iron Rune Construct is out of range.
+ SPELL_CUSTOM_ERROR_REQUIRES_GRAND_MASTER_ENGINEER = 49, // Requires Grand Master Engineer
+ SPELL_CUSTOM_ERROR_CANT_USE_THAT_MOUNT = 50, // You can't use that mount.
+ SPELL_CUSTOM_ERROR_NOONE_TO_EJECT = 51, // There is nobody to eject!
+ SPELL_CUSTOM_ERROR_TARGET_MUST_BE_BOUND = 52, // The target must be bound to you.
+ SPELL_CUSTOM_ERROR_TARGET_MUST_BE_UNDEAD = 53, // Target must be undead.
+ SPELL_CUSTOM_ERROR_TARGET_TOO_FAR = 54, // You have no target or your target is too far away.
+ SPELL_CUSTOM_ERROR_MISSING_DARK_MATTER = 55, // Missing Reagents: Dark Matter
+ SPELL_CUSTOM_ERROR_CANT_USE_THAT_ITEM = 56, // You can't use that item
+ SPELL_CUSTOM_ERROR_CANT_DO_WHILE_CYCYLONED = 57, // You can't do that while Cycloned
+ SPELL_CUSTOM_ERROR_TARGET_HAS_SCROLL = 58, // Target is already affected by a scroll
+ SPELL_CUSTOM_ERROR_POISON_TOO_STRONG = 59, // That anti-venom is not strong enough to dispel that poison
+ SPELL_CUSTOM_ERROR_MUST_HAVE_LANCE_EQUIPPED = 60, // You must have a lance equipped.
+ SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_MAIDEN = 61, // You must be near the Maiden of Winter's Breath Lake.
+ SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING = 62, // You have learned everything from that book
+ SPELL_CUSTOM_ERROR_PET_IS_DEAD = 63, // Your pet is dead
+ SPELL_CUSTOM_ERROR_NO_VALID_TARGETS = 64, // There are no valid targets within range.
+ SPELL_CUSTOM_ERROR_GM_ONLY = 65, // Only GMs may use that. Your account has been reported for investigation.
+ SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_58 = 66, // You must reach level 58 to use this portal.
+ SPELL_CUSTOM_ERROR_AT_HONOR_CAP = 67, // You already have the maximum amount of honor.
+ SPELL_CUSTOM_ERROR_MUST_HAVE_DEMONIC_CIRCLE = 75, // You must have a demonic circle active.
+ SPELL_CUSTOM_ERROR_AT_MAX_RAGE = 76, // You already have maximum rage
+ SPELL_CUSTOM_ERROR_REQUIRES_350_ENGINEERING = 77, // Requires Engineering (350)
+ SPELL_CUSTOM_ERROR_SOUL_BELONGS_TO_LICH_KING = 78, // Your soul belongs to the Lich King
+ SPELL_CUSTOM_ERROR_ATTENDANT_HAS_PONY = 79, // Your attendant already has an Argent Pony
+ SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM = 83, // You must have a Fire Totem active.
+ SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES = 84, // You may not bite other vampires.
+ SPELL_CUSTOM_ERROR_PET_ALREADY_AT_YOUR_LEVEL = 85, // Your pet is already at your level.
+ SPELL_CUSTOM_ERROR_MISSING_ITEM_REQUIREMENS = 86, // You do not meet the level requirements for this item.
+ SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS = 87, // There are too many Mutated Abominations.
+ SPELL_CUSTOM_ERROR_ALL_POTIONS_USED = 88, // The potions have all been depleted by Professor Putricide.
+ SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_65 = 90, // Requires level 65
+};
+
enum StealthType
{
STEALTH_GENERAL = 0,
diff --git a/src/server/game/Skills/SkillDiscovery.cpp b/src/server/game/Skills/SkillDiscovery.cpp
index c75d34079b6..c2af8dd1e48 100755
--- a/src/server/game/Skills/SkillDiscovery.cpp
+++ b/src/server/game/Skills/SkillDiscovery.cpp
@@ -191,6 +191,22 @@ uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player)
return 0;
}
+bool HasDiscoveredAllSpells(uint32 spellId, Player* player)
+{
+ SkillDiscoveryMap::const_iterator tab = SkillDiscoveryStore.find(spellId);
+ if (tab == SkillDiscoveryStore.end())
+ return true;
+
+ SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
+ uint32 skillvalue = bounds.first != bounds.second ? player->GetSkillValue(bounds.first->second->skillId) : 0;
+
+ for (SkillDiscoveryList::const_iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter)
+ if (!player->HasSpell(item_iter->spellId))
+ return false;
+
+ return true;
+}
+
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
{
uint32 skillvalue = skillId ? player->GetSkillValue(skillId) : 0;
diff --git a/src/server/game/Skills/SkillDiscovery.h b/src/server/game/Skills/SkillDiscovery.h
index da9a96c4bd9..ae4f3494534 100755
--- a/src/server/game/Skills/SkillDiscovery.h
+++ b/src/server/game/Skills/SkillDiscovery.h
@@ -25,6 +25,7 @@ class Player;
void LoadSkillDiscoveryTable();
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player);
+bool HasDiscoveredAllSpells(uint32 spellId, Player* player);
uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player);
#endif
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index b89e1167f2c..e1f16e50be0 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -425,6 +425,7 @@ m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, Caster)),
m_caster(Caster), m_spellValue(new SpellValue(m_spellInfo))
{
m_customAttr = sSpellMgr->GetSpellCustomAttr(m_spellInfo->Id);
+ m_customError = SPELL_CUSTOM_ERROR_NONE;
m_skipCheck = skipCheck;
m_selfContainer = NULL;
m_referencedFromCurrentSpell = false;
@@ -3742,10 +3743,10 @@ void Spell::SendCastResult(SpellCastResult result)
if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
return;
- SendCastResult((Player*)m_caster,m_spellInfo,m_cast_count,result);
+ SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
}
-void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result)
+void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/)
{
if (result == SPELL_CAST_OK)
return;
@@ -3807,6 +3808,9 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 ca
data << uint32(pProto->ItemLimitCategory);
break;
}
+ case SPELL_FAILED_CUSTOM_ERROR:
+ data << uint32(customError);
+ break;
default:
break;
}
@@ -5009,6 +5013,11 @@ SpellCastResult Spell::CheckCast(bool strict)
return castResult;
}
+ // script hook
+ castResult = CallScriptCheckCastHandlers();
+ if (castResult != SPELL_CAST_OK)
+ return castResult;
+
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
{
// for effects of spells that have only one target
@@ -7216,6 +7225,25 @@ void Spell::PrepareScriptHitHandlers()
(*scritr)->_InitHit();
}
+SpellCastResult Spell::CallScriptCheckCastHandlers()
+{
+ SpellCastResult retVal = SPELL_CAST_OK;
+ for (std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST);
+ std::list<SpellScript::CheckCastHandler>::iterator hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ {
+ SpellCastResult tempResult = (*hookItr).Call(*scritr);
+ if (retVal == SPELL_CAST_OK)
+ retVal = tempResult;
+ }
+
+ (*scritr)->_FinishScriptCall();
+ }
+ return retVal;
+}
+
bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex)
{
// execute script effect handler hooks and check if effects was prevented
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index d83107f1db3..55b8d38820a 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -470,7 +470,7 @@ class Spell
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.setSrc(*m_caster); }
void CheckDst() { if (!m_targets.HasDst()) m_targets.setDst(*m_caster); }
- static void SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result);
+ static void SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE);
void SendCastResult(SpellCastResult result);
void SendSpellStart();
void SendSpellGo();
@@ -503,6 +503,7 @@ class Spell
uint32 m_preCastSpell;
SpellCastTargets m_targets;
int8 m_comboPointGain;
+ SpellCustomErrors m_customError;
UsedSpellMods m_appliedMods;
@@ -687,6 +688,7 @@ class Spell
// Scripting system
void LoadScripts();
+ SpellCastResult CallScriptCheckCastHandlers();
void PrepareScriptHitHandlers();
bool CallScriptEffectHandlers(SpellEffIndex effIndex);
void CallScriptBeforeHitHandlers();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index d2709c1d4d1..984895b85db 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5126,7 +5126,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
return;
// learn random explicit discovery recipe (if any)
- if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
+ if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, m_caster->ToPlayer()))
m_caster->ToPlayer()->learnSpell(discoveredSpell, false);
return;
}
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 52a06bd1f2e..fcb3bef7e30 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -146,6 +146,16 @@ std::string _SpellScript::EffectAuraNameCheck::ToString()
}
}
+SpellScript::CheckCastHandler::CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript)
+{
+ _checkCastHandlerScript = checkCastHandlerScript;
+}
+
+SpellCastResult SpellScript::CheckCastHandler::Call(SpellScript* spellScript)
+{
+ return (spellScript->*_checkCastHandlerScript)();
+}
+
SpellScript::EffectHandler::EffectHandler(SpellEffectFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName)
: _SpellScript::EffectNameCheck(_effName), _SpellScript::EffectHook(_effIndex)
{
@@ -445,6 +455,17 @@ void SpellScript::FinishCast(SpellCastResult result)
m_spell->finish(result == SPELL_CAST_OK);
}
+void SpellScript::SetCustomCastResultMessage(SpellCustomErrors result)
+{
+ if (!IsInCheckCastHook())
+ {
+ sLog->outError("TSCR: Script: `%s` Spell: `%u`: function SpellScript::SetCustomCastResultMessage was called while spell not in check cast phase!", m_scriptName->c_str(), m_scriptSpellId);
+ return;
+ }
+
+ m_spell->m_customError = result;
+}
+
bool AuraScript::_Validate(SpellEntry const * entry)
{
for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 6a57befef41..4510b1b9f3b 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -121,11 +121,12 @@ enum SpellScriptHookType
SPELL_SCRIPT_HOOK_HIT,
SPELL_SCRIPT_HOOK_AFTER_HIT,
SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT,
+ SPELL_SCRIPT_HOOK_CHECK_CAST,
};
#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT
#define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1
#define HOOK_SPELL_START SPELL_SCRIPT_HOOK_EFFECT
-#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT + 1
+#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1
#define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START
class SpellScript : public _SpellScript
@@ -134,12 +135,22 @@ class SpellScript : public _SpellScript
// DO NOT OVERRIDE THESE IN SCRIPTS
public:
#define SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \
+ typedef SpellCastResult(CLASSNAME::*SpellCheckCastFnType)(); \
typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \
typedef void(CLASSNAME::*SpellHitFnType)(); \
typedef void(CLASSNAME::*SpellUnitTargetFnType)(std::list<Unit*>&); \
SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript)
+ class CheckCastHandler
+ {
+ public:
+ CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript);
+ SpellCastResult Call(SpellScript* spellScript);
+ private:
+ SpellCheckCastFnType _checkCastHandlerScript;
+ };
+
class EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook
{
public:
@@ -173,6 +184,7 @@ class SpellScript : public _SpellScript
};
#define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
+ class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) {} }; \
class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \
class UnitTargetHandlerFunction : public SpellScript::UnitTargetHandler { public: UnitTargetHandlerFunction(SpellUnitTargetFnType _pUnitTargetHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::UnitTargetHandler((SpellScript::SpellUnitTargetFnType)_pUnitTargetHandlerScript, _effIndex, _targetType) {} }; \
@@ -186,8 +198,9 @@ class SpellScript : public _SpellScript
bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) { return m_hitPreventDefaultEffectMask & (1<<effIndex); }
void _PrepareScriptCall(SpellScriptHookType hookType);
void _FinishScriptCall();
- bool IsInHitPhase() { return (m_currentScriptState >= HOOK_SPELL_HIT_START && m_currentScriptState < HOOK_SPELL_HIT_END); }
- bool IsInEffectHook() { return (m_currentScriptState == SPELL_SCRIPT_HOOK_EFFECT); }
+ bool IsInCheckCastHook() const { return m_currentScriptState == SPELL_SCRIPT_HOOK_CHECK_CAST; }
+ bool IsInHitPhase() const { return (m_currentScriptState >= HOOK_SPELL_HIT_START && m_currentScriptState < HOOK_SPELL_HIT_END); }
+ bool IsInEffectHook() const { return (m_currentScriptState == SPELL_SCRIPT_HOOK_EFFECT); }
private:
Spell * m_spell;
uint8 m_hitPreventEffectMask;
@@ -197,6 +210,12 @@ class SpellScript : public _SpellScript
// SpellScript interface
// hooks to which you can attach your functions
//
+
+ // example: OnCheckCast += SpellCheckCastFn();
+ // where function is SpellCastResult function()
+ HookList<CheckCastHandler> OnCheckCast;
+ #define SpellCheckCastFn(F) CheckCastHandlerFunction(&F)
+
// example: OnEffect += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier);
// where function is void function(SpellEffIndex effIndex)
HookList<EffectHandler> OnEffect;
@@ -294,6 +313,8 @@ class SpellScript : public _SpellScript
// finishes spellcast prematurely with selected error message
void FinishCast(SpellCastResult result);
+
+ void SetCustomCastResultMessage(SpellCustomErrors result);
};
// AuraScript interface - enum used for runtime checks of script function calls
@@ -454,7 +475,7 @@ class AuraScript : public _SpellScript
// executed when periodic aura effect is updated
// example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
- // where function is: void function (AuraEffect const * aurEff);
+ // where function is: void function (AuraEffect * aurEff);
HookList<EffectUpdatePeriodicHandler> OnEffectUpdatePeriodic;
#define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandlerFunction(&F, I, N)
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 5befce55949..63df688b92f 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -24,6 +24,7 @@
#include "ScriptPCH.h"
#include "SpellAuraEffects.h"
+#include "SkillDiscovery.h"
class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader
{
@@ -766,6 +767,38 @@ class spell_gen_dungeon_credit : public SpellScriptLoader
}
};
+class spell_gen_profession_research : public SpellScriptLoader
+{
+ public:
+ spell_gen_profession_research() : SpellScriptLoader("spell_gen_profession_research") {}
+
+ class spell_gen_profession_research_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_profession_research_SpellScript);
+
+ SpellCastResult CheckRequirement()
+ {
+ if (GetCaster()->GetTypeId() == TYPEID_PLAYER && HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
+ {
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
+
+ return SPELL_CAST_OK;
+ }
+
+ void Register()
+ {
+ OnCheckCast += SpellCheckCastFn(spell_gen_profession_research_SpellScript::CheckRequirement);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gen_profession_research_SpellScript();
+ }
+};
+
void AddSC_generic_spell_scripts()
{
new spell_gen_absorb0_hitlimit1();
@@ -785,4 +818,5 @@ void AddSC_generic_spell_scripts()
new spell_gen_parachute_ic();
new spell_gen_gunship_portal();
new spell_gen_dungeon_credit();
+ new spell_gen_profession_research();
}
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 43589c68180..4cffbdf4437 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -22,6 +22,7 @@
*/
#include "ScriptPCH.h"
+#include "SkillDiscovery.h"
// Generic script for handling item dummy effects which trigger another spell.
class spell_item_trigger_spell : public SpellScriptLoader
@@ -849,6 +850,38 @@ class spell_item_create_heart_candy : public SpellScriptLoader
}
};
+class spell_item_book_of_glyph_mastery : public SpellScriptLoader
+{
+ public:
+ spell_item_book_of_glyph_mastery() : SpellScriptLoader("spell_item_book_of_glyph_mastery") {}
+
+ class spell_item_book_of_glyph_mastery_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_item_book_of_glyph_mastery_SpellScript);
+
+ SpellCastResult CheckRequirement()
+ {
+ if (GetCaster()->GetTypeId() == TYPEID_PLAYER && HasDiscoveredAllSpells(GetSpellInfo()->Id, GetCaster()->ToPlayer()))
+ {
+ SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING);
+ return SPELL_FAILED_CUSTOM_ERROR;
+ }
+
+ return SPELL_CAST_OK;
+ }
+
+ void Register()
+ {
+ OnCheckCast += SpellCheckCastFn(spell_item_book_of_glyph_mastery_SpellScript::CheckRequirement);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_item_book_of_glyph_mastery_SpellScript();
+ }
+};
+
void AddSC_item_spell_scripts()
{
// 23074 Arcanite Dragonling
@@ -874,4 +907,5 @@ void AddSC_item_spell_scripts()
new spell_item_red_rider_air_rifle();
new spell_item_create_heart_candy();
+ new spell_item_book_of_glyph_mastery();
}