[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 <schmoozerd@scriptdev2.com>
This commit is contained in:
Schmoozerd 2012-05-08 17:28:30 +02:00
parent dd1d913ff2
commit 83d7d86255
9 changed files with 86 additions and 22 deletions

View file

@ -11,6 +11,7 @@ Copyright (C) 2010-2012 MaNGOS <http://getmangos.com/>
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)
-- --------------------------

View file

@ -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)

View file

@ -215,7 +215,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
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

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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);
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11988"
#define REVISION_NR "11989"
#endif // __REVISION_NR_H__