From 83d7d8625559c2ecb4fadeaa8a87c229af8bf85a Mon Sep 17 00:00:00 2001 From: Schmoozerd Date: Tue, 8 May 2012 17:28:30 +0200 Subject: [PATCH] [11989] Add support to call spell_scripts in more cases * Support to script Dummy spells with spell_scripts * Support to script TriggerSpell spells which have no existing triggered spell Note that the order which spell-effect actually triggers the DB script is well-defined (SCRIPT_EFFECT before DUMMY before other) Signed-off-by: Schmoozerd --- doc/script_commands.txt | 6 ++++- src/game/Map.cpp | 6 +++-- src/game/Map.h | 2 +- src/game/ScriptMgr.cpp | 52 +++++++++++++++++++++++++++++++-------- src/game/ScriptMgr.h | 1 + src/game/Spell.cpp | 2 +- src/game/Spell.h | 1 + src/game/SpellEffects.cpp | 36 ++++++++++++++++++++++----- src/shared/revision_nr.h | 2 +- 9 files changed, 86 insertions(+), 22 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index e3799b1f2..624700a10 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -11,6 +11,7 @@ Copyright (C) 2010-2012 MaNGOS creature_movement_scripts DB project self defined id event_scripts Event id. Several sources: spell effect 61, taxi/transport nodes, gameobject_template data gameobject_scripts Gameobject guid +gameobject_template_scripts Gameobject entry gossip_scripts DB project self defined id quest_end_scripts DB project self defined id (generally quest entry) quest_start_scripts DB project self defined id (generally quest entry) @@ -90,6 +91,7 @@ event_scripts Spell (effect 61) Source: caster. Target: Target gameobject_scripts +gameobject_template_scripts Gameobject use Source: user: Target: GO gossip_scripts @@ -103,7 +105,9 @@ quest_start_scripts `quest_template` Source: quest giver (creature/GO). Target: player spell_scripts - Spell (effect 77) + Spell (effect 77 - SCRIPT_EFFECT) + Spell (effect 3 - DUMMY) + Spell (effect 64 - TRIGGER_SPELL, with non-existing triggered spell) Source: caster: Target: target of spell (Unit) -- -------------------------- diff --git a/src/game/Map.cpp b/src/game/Map.cpp index f7ef79b2f..3f418da70 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1606,12 +1606,12 @@ void BattleGroundMap::UnloadAll(bool pForce) } /// Put scripts in the execution queue -void Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target) +bool Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target) { ///- Find the script map ScriptMapMap::const_iterator s = scripts.second.find(id); if (s == scripts.second.end()) - return; + return false; // prepare static data ObjectGuid sourceGuid = source->GetObjectGuid(); @@ -1634,6 +1634,8 @@ void Map::ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* sourc ///- If one of the effects should be immediate, launch the script execution if (immedScript) ScriptsProcess(); + + return true; } void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) diff --git a/src/game/Map.h b/src/game/Map.h index f442f2da1..a3111ee58 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -215,7 +215,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager PlayerList const& GetPlayers() const { return m_mapRefManager; } //per-map script storage - void ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target); + bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); // must called with AddToWorld diff --git a/src/game/ScriptMgr.cpp b/src/game/ScriptMgr.cpp index f6ba08adc..c4d34ee45 100644 --- a/src/game/ScriptMgr.cpp +++ b/src/game/ScriptMgr.cpp @@ -85,6 +85,43 @@ ScriptMgr::~ScriptMgr() // ///////////////////////////////////////////////////////// // DB SCRIPTS (loaders of static data) // ///////////////////////////////////////////////////////// +// returns priority (0 == cannot start script) +uint8 GetSpellStartDBScriptPriority(SpellEntry const* spellinfo, SpellEffectIndex effIdx) +{ + if (spellinfo->Effect[effIdx] == SPELL_EFFECT_SCRIPT_EFFECT) + return 10; + + if (spellinfo->Effect[effIdx] == SPELL_EFFECT_DUMMY) + return 9; + + // NonExisting triggered spells can also start DB-Spell-Scripts + if (spellinfo->Effect[effIdx] == SPELL_EFFECT_TRIGGER_SPELL && !sSpellStore.LookupEntry(spellinfo->EffectTriggerSpell[effIdx])) + return 5; + + // Can not start script + return 0; +} + +// Priorize: SCRIPT_EFFECT before DUMMY before Non-Existing triggered spell, for same priority the first effect with the priority triggers +bool ScriptMgr::CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEffectIndex effIdx) +{ + uint8 priority = GetSpellStartDBScriptPriority(spellinfo, effIdx); + if (!priority) + return false; + + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + uint8 currentPriority = GetSpellStartDBScriptPriority(spellinfo, SpellEffectIndex(i)); + if (currentPriority < priority) // lower priority, continue checking + continue; + if (currentPriority > priority) // take other index with higher priority + return false; + if (i < effIdx) // same priority at lower index + return false; + } + + return true; +} void ScriptMgr::LoadScripts(ScriptMapMapName& scripts, const char* tablename) { @@ -640,25 +677,20 @@ void ScriptMgr::LoadSpellScripts() LoadScripts(sSpellScripts, "spell_scripts"); // check ids - for(ScriptMapMap::const_iterator itr = sSpellScripts.second.begin(); itr != sSpellScripts.second.end(); ++itr) + for (ScriptMapMap::const_iterator itr = sSpellScripts.second.begin(); itr != sSpellScripts.second.end(); ++itr) { SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo) { sLog.outErrorDb("Table `spell_scripts` has not existing spell (Id: %u) as script id", itr->first); continue; } - //check for correct spellEffect + // check for correct spellEffect bool found = false; - for(int i = 0; i < MAX_EFFECT_INDEX; ++i) + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { - // skip empty effects - if (!spellInfo->Effect[i]) - continue; - - if (spellInfo->Effect[i] == SPELL_EFFECT_SCRIPT_EFFECT) + if (GetSpellStartDBScriptPriority(spellInfo, SpellEffectIndex(i))) { found = true; break; @@ -666,7 +698,7 @@ void ScriptMgr::LoadSpellScripts() } if (!found) - sLog.outErrorDb("Table `spell_scripts` has unsupported spell (Id: %u) without SPELL_EFFECT_SCRIPT_EFFECT (%u) spell effect", itr->first, SPELL_EFFECT_SCRIPT_EFFECT); + sLog.outErrorDb("Table `spell_scripts` has unsupported spell (Id: %u)", itr->first); } } diff --git a/src/game/ScriptMgr.h b/src/game/ScriptMgr.h index fd493ac57..0adbf7123 100644 --- a/src/game/ScriptMgr.h +++ b/src/game/ScriptMgr.h @@ -437,6 +437,7 @@ class ScriptMgr uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; } uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); } bool IsScriptScheduled() const { return m_scheduledScripts > 0; } + static bool CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEffectIndex effIdx); CreatureAI* GetCreatureAI(Creature* pCreature); InstanceData* CreateInstanceData(Map* pMap); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 39f636cc5..a064b2fe7 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -846,7 +846,7 @@ void Spell::AddUnitTarget(Unit* pVictim, SpellEffectIndex effIndex) TargetInfo target; target.targetGUID = targetGUID; // Store target GUID target.effectMask = immuned ? 0 : (1 << effIndex); // Store index of effect if not immuned - target.processed = false; // Effects not apply on target + target.processed = false; // Effects not applied on target // Calculate hit result target.missCondition = m_caster->SpellHitResult(pVictim, m_spellInfo, m_canReflect); diff --git a/src/game/Spell.h b/src/game/Spell.h index 90e10b923..00708d9bc 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -495,6 +495,7 @@ class Spell void ClearCastItem(); static void SelectMountByAreaAndSkill(Unit* target, SpellEntry const* parentSpell, uint32 spellId75, uint32 spellId150, uint32 spellId225, uint32 spellId300, uint32 spellIdSpecial); + protected: bool HasGlobalCooldown(); void TriggerGlobalCooldown(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 062380b9c..908cc9d2a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3333,12 +3333,23 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) // Script based implementation. Must be used only for not good for implementation in core spell effects // So called only for not processed cases + bool libraryResult = false; if (gameObjTarget) - sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, gameObjTarget); + libraryResult = sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, gameObjTarget); else if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT) - sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, (Creature*)unitTarget); + libraryResult = sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, (Creature*)unitTarget); else if (itemTarget) - sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, itemTarget); + libraryResult = sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, eff_idx, itemTarget); + + if (libraryResult || !unitTarget) + return; + + // Previous effect might have started script + if (!ScriptMgr::CanSpellEffectStartDBScript(m_spellInfo, eff_idx)) + return; + + DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectDummy", m_spellInfo->Id); + m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); } void Spell::EffectTriggerSpellWithValue(SpellEffectIndex eff_idx) @@ -3518,10 +3529,19 @@ void Spell::EffectTriggerSpell(SpellEffectIndex effIndex) } // normal case - SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); + SpellEntry const* spellInfo = sSpellStore.LookupEntry(triggered_spell_id); if (!spellInfo) { - sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); + // No previous Effect might have started a script + bool startDBScript = unitTarget && ScriptMgr::CanSpellEffectStartDBScript(m_spellInfo, effIndex); + if (startDBScript) + { + DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectTriggerSpell", m_spellInfo->Id); + startDBScript = m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); + } + + if (!startDBScript) + sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id); return; } @@ -8039,7 +8059,11 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx) if (!unitTarget) return; - DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id); + // Previous effect might have started script + if (!ScriptMgr::CanSpellEffectStartDBScript(m_spellInfo, eff_idx)) + return; + + DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart spellid %u in EffectScriptEffect", m_spellInfo->Id); m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eda69b72f..e31dedabc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11988" + #define REVISION_NR "11989" #endif // __REVISION_NR_H__