Core/Spells: Implement using different difficulty data from all spell related db2s, not just SpellEffect and SpellPower
Port From (https://github.com/TrinityCore/TrinityCore/commit/c7306439e7004288fb85890d6a5f730cf1761d71)
This commit is contained in:
@@ -28,7 +28,7 @@ namespace Game.AI
|
||||
public override void InitializeAI()
|
||||
{
|
||||
for (var i = 0; i < SharedConst.MaxCreatureSpells; ++i)
|
||||
if (me.m_spells[i] != 0 && Global.SpellMgr.GetSpellInfo(me.m_spells[i]) != null)
|
||||
if (me.m_spells[i] != 0 && Global.SpellMgr.HasSpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID()))
|
||||
spells.Add(me.m_spells[i]);
|
||||
|
||||
base.InitializeAI();
|
||||
@@ -42,18 +42,22 @@ namespace Game.AI
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
foreach (var id in spells)
|
||||
if (AISpellInfo[id].condition == AICondition.Die)
|
||||
{
|
||||
AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
|
||||
if (info.condition == AICondition.Die)
|
||||
me.CastSpell(killer, id, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit victim)
|
||||
{
|
||||
foreach (var id in spells)
|
||||
{
|
||||
if (AISpellInfo[id].condition == AICondition.Aggro)
|
||||
AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
|
||||
if (info.condition == AICondition.Aggro)
|
||||
me.CastSpell(victim, id, false);
|
||||
else if (AISpellInfo[id].condition == AICondition.Combat)
|
||||
_events.ScheduleEvent(id, AISpellInfo[id].cooldown + RandomHelper.Rand32() % AISpellInfo[id].cooldown);
|
||||
else if (info.condition == AICondition.Combat)
|
||||
_events.ScheduleEvent(id, info.cooldown + RandomHelper.Rand32() % info.cooldown);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +75,11 @@ namespace Game.AI
|
||||
if (spellId != 0)
|
||||
{
|
||||
DoCast(spellId);
|
||||
_events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + RandomHelper.Rand32() % AISpellInfo[spellId].cooldown);
|
||||
AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());
|
||||
_events.ScheduleEvent(spellId, info.cooldown + RandomHelper.Rand32() % info.cooldown);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void SpellInterrupted(uint spellId, uint unTimeMs)
|
||||
@@ -112,8 +117,12 @@ namespace Game.AI
|
||||
|
||||
m_attackDist = 30.0f;
|
||||
foreach (var id in spells)
|
||||
if (AISpellInfo[id].condition == AICondition.Combat && m_attackDist > AISpellInfo[id].maxRange)
|
||||
m_attackDist = AISpellInfo[id].maxRange;
|
||||
{
|
||||
AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
|
||||
if (info.condition == AICondition.Combat && m_attackDist > info.maxRange)
|
||||
m_attackDist = info.maxRange;
|
||||
}
|
||||
|
||||
if (m_attackDist == 30.0f)
|
||||
m_attackDist = SharedConst.MeleeRange;
|
||||
}
|
||||
@@ -132,12 +141,12 @@ namespace Game.AI
|
||||
uint count = 0;
|
||||
foreach (var id in spells)
|
||||
{
|
||||
|
||||
if (AISpellInfo[id].condition == AICondition.Aggro)
|
||||
AISpellInfoType info = GetAISpellInfo(id, me.GetMap().GetDifficultyID());
|
||||
if (info.condition == AICondition.Aggro)
|
||||
me.CastSpell(victim, id, false);
|
||||
else if (AISpellInfo[id].condition == AICondition.Combat)
|
||||
else if (info.condition == AICondition.Combat)
|
||||
{
|
||||
uint cooldown = AISpellInfo[id].realCooldown;
|
||||
uint cooldown = info.realCooldown;
|
||||
if (count == spell)
|
||||
{
|
||||
DoCast(spells[spell]);
|
||||
@@ -169,7 +178,8 @@ namespace Game.AI
|
||||
{
|
||||
DoCast(spellId);
|
||||
uint casttime = (uint)me.GetCurrentSpellCastTime(spellId);
|
||||
_events.ScheduleEvent(spellId, (casttime != 0 ? casttime : 500) + AISpellInfo[spellId].realCooldown);
|
||||
AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());
|
||||
_events.ScheduleEvent(spellId, (casttime != 0 ? casttime : 500) + info.realCooldown);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +194,7 @@ namespace Game.AI
|
||||
if (me.m_spells[0] == 0)
|
||||
Log.outError(LogFilter.ScriptsAi, "ArcherAI set for creature (entry = {0}) with spell1=0. AI will do nothing", me.GetEntry());
|
||||
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.m_spells[0]);
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.m_spells[0], me.GetMap().GetDifficultyID());
|
||||
m_minRange = spellInfo != null ? spellInfo.GetMinRange(false) : 0;
|
||||
|
||||
if (m_minRange == 0)
|
||||
@@ -234,7 +244,7 @@ namespace Game.AI
|
||||
if (me.m_spells[0] == 0)
|
||||
Log.outError(LogFilter.Server, "TurretAI set for creature (entry = {0}) with spell1=0. AI will do nothing", me.GetEntry());
|
||||
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.m_spells[0]);
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.m_spells[0], me.GetMap().GetDifficultyID());
|
||||
m_minRange = spellInfo != null ? spellInfo.GetMinRange(false) : 0;
|
||||
me.m_CombatDistance = spellInfo != null ? spellInfo.GetMaxRange(false) : 0;
|
||||
me.m_SightDistance = me.m_CombatDistance;
|
||||
|
||||
@@ -492,6 +492,9 @@ namespace Game.AI
|
||||
public uint cooldown;
|
||||
public uint realCooldown;
|
||||
public float maxRange;
|
||||
|
||||
public byte Targets; // set of enum SelectTarget
|
||||
public byte Effects; // set of enum SelectEffect
|
||||
}
|
||||
|
||||
public enum AITarget
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Game.AI
|
||||
if (spellID == 0)
|
||||
continue;
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellID);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellID, me.GetMap().GetDifficultyID());
|
||||
if (spellInfo == null)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Game.AI
|
||||
return;
|
||||
|
||||
// Search spell
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.ToTotem().GetSpell());
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(me.ToTotem().GetSpell(), me.GetMap().GetDifficultyID());
|
||||
if (spellInfo == null)
|
||||
return;
|
||||
|
||||
|
||||
+105
-25
@@ -31,7 +31,7 @@ namespace Game.AI
|
||||
{
|
||||
me = _unit;
|
||||
}
|
||||
|
||||
|
||||
public virtual void AttackStart(Unit victim)
|
||||
{
|
||||
if (victim != null && me.Attack(victim, true))
|
||||
@@ -99,7 +99,7 @@ namespace Game.AI
|
||||
if (me.HasUnitState(UnitState.Casting) || !me.IsAttackReady())
|
||||
return true;
|
||||
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spell);
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spell, me.GetMap().GetDifficultyID());
|
||||
if (spellInfo != null)
|
||||
{
|
||||
if (me.IsWithinCombatRange(me.GetVictim(), spellInfo.GetMaxRange(false)))
|
||||
@@ -156,18 +156,18 @@ namespace Game.AI
|
||||
{
|
||||
case SelectAggroTarget.Nearest:
|
||||
case SelectAggroTarget.TopAggro:
|
||||
{
|
||||
return targetList.First();
|
||||
}
|
||||
{
|
||||
return targetList.First();
|
||||
}
|
||||
case SelectAggroTarget.Farthest:
|
||||
case SelectAggroTarget.BottomAggro:
|
||||
{
|
||||
return targetList.Last();
|
||||
}
|
||||
{
|
||||
return targetList.Last();
|
||||
}
|
||||
case SelectAggroTarget.Random:
|
||||
{
|
||||
return targetList.SelectRandom();
|
||||
}
|
||||
{
|
||||
return targetList.SelectRandom();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -179,7 +179,7 @@ namespace Game.AI
|
||||
{
|
||||
return SelectTargetList(new DefaultTargetSelector(me, dist, playerOnly, aura), num, targetType);
|
||||
}
|
||||
|
||||
|
||||
// Select the targets satifying the predicate.
|
||||
// predicate shall extend std.unary_function<Unit*, bool>
|
||||
public List<Unit> SelectTargetList(ISelector selector, uint maxTargets, SelectAggroTarget targetType)
|
||||
@@ -215,7 +215,8 @@ namespace Game.AI
|
||||
{
|
||||
Unit target = null;
|
||||
|
||||
switch (AISpellInfo[spellId].target)
|
||||
AISpellInfoType info = GetAISpellInfo(spellId, me.GetMap().GetDifficultyID());
|
||||
switch (info.target)
|
||||
{
|
||||
default:
|
||||
case AITarget.Self:
|
||||
@@ -226,7 +227,7 @@ namespace Game.AI
|
||||
break;
|
||||
case AITarget.Enemy:
|
||||
{
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spellId);
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spellId, me.GetMap().GetDifficultyID());
|
||||
if (spellInfo != null)
|
||||
{
|
||||
bool playerOnly = spellInfo.HasAttribute(SpellAttr3.OnlyTargetPlayers);
|
||||
@@ -240,7 +241,7 @@ namespace Game.AI
|
||||
break;
|
||||
case AITarget.Debuff:
|
||||
{
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spellId);
|
||||
var spellInfo = Global.SpellMgr.GetSpellInfo(spellId, me.GetMap().GetDifficultyID());
|
||||
if (spellInfo != null)
|
||||
{
|
||||
bool playerOnly = spellInfo.HasAttribute(SpellAttr3.OnlyTargetPlayers);
|
||||
@@ -289,12 +290,11 @@ namespace Game.AI
|
||||
|
||||
public static void FillAISpellInfo()
|
||||
{
|
||||
var spellStorage = Global.SpellMgr.GetSpellInfoStorage();
|
||||
AISpellInfo = new AISpellInfoType[spellStorage.Keys.Max() + 1];
|
||||
//AISpellInfo = new AISpellInfoType[spellStorage.Keys.Max() + 1];
|
||||
|
||||
foreach (var spellInfo in spellStorage.Values)
|
||||
Global.SpellMgr.ForEachSpellInfo(spellInfo =>
|
||||
{
|
||||
AISpellInfoType AIInfo = AISpellInfo[spellInfo.Id];
|
||||
AISpellInfoType AIInfo = new AISpellInfoType();
|
||||
if (spellInfo.HasAttribute(SpellAttr0.CastableWhileDead))
|
||||
AIInfo.condition = AICondition.Die;
|
||||
else if (spellInfo.IsPassive() || spellInfo.GetDuration() == -1)
|
||||
@@ -312,14 +312,14 @@ namespace Game.AI
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffects())
|
||||
{
|
||||
if (effect == null)
|
||||
continue;
|
||||
|
||||
var targetType = effect.TargetA.GetTarget();
|
||||
|
||||
if (targetType == Targets.UnitEnemy || targetType == Targets.DestEnemy)
|
||||
if (targetType == Targets.UnitTargetEnemy || targetType == Targets.DestTargetEnemy)
|
||||
{
|
||||
if (AIInfo.target < AITarget.Victim)
|
||||
AIInfo.target = AITarget.Victim;
|
||||
@@ -332,7 +332,7 @@ namespace Game.AI
|
||||
|
||||
if (effect.Effect == SpellEffectName.ApplyAura)
|
||||
{
|
||||
if (targetType == Targets.UnitEnemy)
|
||||
if (targetType == Targets.UnitTargetEnemy)
|
||||
{
|
||||
if (AIInfo.target < AITarget.Debuff)
|
||||
AIInfo.target = AITarget.Debuff;
|
||||
@@ -347,7 +347,82 @@ namespace Game.AI
|
||||
}
|
||||
AIInfo.realCooldown = spellInfo.RecoveryTime + spellInfo.StartRecoveryTime;
|
||||
AIInfo.maxRange = spellInfo.GetMaxRange(false) * 3 / 4;
|
||||
}
|
||||
|
||||
AIInfo.Effects = 0;
|
||||
AIInfo.Targets = 0;
|
||||
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffects())
|
||||
{
|
||||
if (effect == null)
|
||||
continue;
|
||||
|
||||
// Spell targets self.
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitCaster)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.Self - 1);
|
||||
|
||||
// Spell targets a single enemy.
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitTargetEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.DestTargetEnemy)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.SingleEnemy - 1);
|
||||
|
||||
// Spell targets AoE at enemy.
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitSrcAreaEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitDestAreaEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.SrcCaster ||
|
||||
effect.TargetA.GetTarget() == Targets.DestDynobjEnemy)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.AoeEnemy - 1);
|
||||
|
||||
// Spell targets an enemy.
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitTargetEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.DestTargetEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitSrcAreaEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitDestAreaEnemy ||
|
||||
effect.TargetA.GetTarget() == Targets.SrcCaster ||
|
||||
effect.TargetA.GetTarget() == Targets.DestDynobjEnemy)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.AnyEnemy - 1);
|
||||
|
||||
// Spell targets a single friend (or self).
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitCaster ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitTargetAlly ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitTargetParty)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.SingleFriend - 1);
|
||||
|
||||
// Spell targets AoE friends.
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitCasterAreaParty ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitLastTargetAreaParty ||
|
||||
effect.TargetA.GetTarget() == Targets.SrcCaster)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.AoeFriend - 1);
|
||||
|
||||
// Spell targets any friend (or self).
|
||||
if (effect.TargetA.GetTarget() == Targets.UnitCaster ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitTargetAlly ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitTargetParty ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitCasterAreaParty ||
|
||||
effect.TargetA.GetTarget() == Targets.UnitLastTargetAreaParty ||
|
||||
effect.TargetA.GetTarget() == Targets.SrcCaster)
|
||||
AIInfo.Targets |= 1 << ((int)SelectTargetType.AnyFriend - 1);
|
||||
|
||||
// Make sure that this spell includes a damage effect.
|
||||
if (effect.Effect == SpellEffectName.SchoolDamage ||
|
||||
effect.Effect == SpellEffectName.Instakill ||
|
||||
effect.Effect == SpellEffectName.EnvironmentalDamage ||
|
||||
effect.Effect == SpellEffectName.HealthLeech)
|
||||
AIInfo.Effects |= 1 << ((int)SelectEffect.Damage - 1);
|
||||
|
||||
// Make sure that this spell includes a healing effect (or an apply aura with a periodic heal).
|
||||
if (effect.Effect == SpellEffectName.Heal ||
|
||||
effect.Effect == SpellEffectName.HealMaxHealth ||
|
||||
effect.Effect == SpellEffectName.HealMechanical ||
|
||||
(effect.Effect == SpellEffectName.ApplyAura && effect.ApplyAuraName == AuraType.PeriodicHeal))
|
||||
AIInfo.Effects |= 1 << ((int)SelectEffect.Healing - 1);
|
||||
|
||||
// Make sure that this spell applies an aura.
|
||||
if (effect.Effect == SpellEffectName.ApplyAura)
|
||||
AIInfo.Effects |= 1 << ((int)SelectEffect.Aura - 1);
|
||||
}
|
||||
|
||||
AISpellInfo[(spellInfo.Id, spellInfo.Difficulty)] = AIInfo;
|
||||
});
|
||||
}
|
||||
|
||||
public virtual bool CanAIAttack(Unit victim) { return true; }
|
||||
@@ -411,7 +486,12 @@ namespace Game.AI
|
||||
// Called when the dialog status between a player and the creature is requested.
|
||||
public virtual QuestGiverStatus GetDialogStatus(Player player) { return QuestGiverStatus.ScriptedNoStatus; }
|
||||
|
||||
public static AISpellInfoType[] AISpellInfo;
|
||||
public AISpellInfoType GetAISpellInfo(uint spellId, Difficulty difficulty)
|
||||
{
|
||||
return AISpellInfo.LookupByKey((spellId, difficulty));
|
||||
}
|
||||
|
||||
public static Dictionary<(uint id, Difficulty difficulty), AISpellInfoType> AISpellInfo = new Dictionary<(uint id, Difficulty difficulty), AISpellInfoType>();
|
||||
|
||||
protected Unit me { get; private set; }
|
||||
}
|
||||
@@ -493,7 +573,7 @@ namespace Game.AI
|
||||
public SpellTargetSelector(Unit caster, uint spellId)
|
||||
{
|
||||
_caster = caster;
|
||||
_spellInfo = Global.SpellMgr.GetSpellInfo(spellId);
|
||||
_spellInfo = Global.SpellMgr.GetSpellInfo(spellId, caster.GetMap().GetDifficultyID());
|
||||
|
||||
Cypher.Assert(_spellInfo != null);
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace Game.AI
|
||||
if (knownRank == 0)
|
||||
return null;
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(knownRank);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(knownRank, me.GetMap().GetDifficultyID());
|
||||
if (spellInfo == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -136,7 +136,8 @@ namespace Game.AI
|
||||
//Check if each spell is viable(set it to null if not)
|
||||
for (uint i = 0; i < SharedConst.MaxCreatureSpells; i++)
|
||||
{
|
||||
SpellInfo tempSpell = Global.SpellMgr.GetSpellInfo(me.m_spells[i]);
|
||||
SpellInfo tempSpell = Global.SpellMgr.GetSpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID());
|
||||
AISpellInfoType aiSpell = GetAISpellInfo(me.m_spells[i], me.GetMap().GetDifficultyID());
|
||||
|
||||
//This spell doesn't exist
|
||||
if (tempSpell == null)
|
||||
@@ -144,11 +145,11 @@ namespace Game.AI
|
||||
|
||||
// Targets and Effects checked first as most used restrictions
|
||||
//Check the spell targets if specified
|
||||
if (targets != 0 && !Convert.ToBoolean(Global.ScriptMgr.spellSummaryStorage[me.m_spells[i]].Targets & (1 << ((int)targets - 1))))
|
||||
if (targets != 0 && !Convert.ToBoolean(aiSpell.Targets & (1 << ((int)targets - 1))))
|
||||
continue;
|
||||
|
||||
//Check the type of spell if we are looking for a specific spell type
|
||||
if (effect != 0 && !Convert.ToBoolean(Global.ScriptMgr.spellSummaryStorage[me.m_spells[i]].Effects & (1 << ((int)effect - 1))))
|
||||
if (effect != 0 && !Convert.ToBoolean(aiSpell.Effects & (1 << ((int)effect - 1))))
|
||||
continue;
|
||||
|
||||
//Check for school if specified
|
||||
|
||||
@@ -656,7 +656,7 @@ namespace Game.AI
|
||||
|
||||
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
||||
{
|
||||
GetScript().ProcessEventsFor(SmartEvents.SpellhitTarget, target, 0, 0, false, spell);
|
||||
GetScript().ProcessEventsFor(SmartEvents.SpellHitTarget, target, 0, 0, false, spell);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Game.AI
|
||||
}
|
||||
case SmartScriptType.Spell:
|
||||
{
|
||||
if (!Global.SpellMgr.HasSpellInfo((uint)temp.entryOrGuid))
|
||||
if (!Global.SpellMgr.HasSpellInfo((uint)temp.entryOrGuid, Difficulty.None))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "SmartAIMgr.LoadSmartAIFromDB: Scene id ({0}) does not exist, skipped loading.", temp.entryOrGuid);
|
||||
continue;
|
||||
@@ -505,10 +505,10 @@ namespace Game.AI
|
||||
return false;
|
||||
break;
|
||||
case SmartEvents.SpellHit:
|
||||
case SmartEvents.SpellhitTarget:
|
||||
case SmartEvents.SpellHitTarget:
|
||||
if (e.Event.spellHit.spell != 0)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Event.spellHit.spell);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Event.spellHit.spell, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Entry {0} SourceType {1} Event {2} Action {3} uses non-existent Spell entry {4}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.Event.spellHit.spell);
|
||||
@@ -571,6 +571,15 @@ namespace Game.AI
|
||||
return false;
|
||||
break;
|
||||
case SmartEvents.VictimCasting:
|
||||
if (e.Event.targetCasting.spellId > 0 && !Global.SpellMgr.HasSpellInfo(e.Event.targetCasting.spellId, Difficulty.None))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"SmartAIMgr: Entry {e.entryOrGuid} SourceType {e.GetScriptType()} Event {e.event_id} Action {e.GetActionType()} uses non-existent Spell entry {e.Event.spellHit.spell}, skipped.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMinMaxValid(e, e.Event.minMax.repeatMin, e.Event.minMax.repeatMax))
|
||||
return false;
|
||||
break;
|
||||
case SmartEvents.PassengerBoarded:
|
||||
case SmartEvents.PassengerRemoved:
|
||||
if (!IsMinMaxValid(e, e.Event.minMax.repeatMin, e.Event.minMax.repeatMax))
|
||||
@@ -912,8 +921,8 @@ namespace Game.AI
|
||||
if (!IsSpellValid(e, e.Action.cast.spell))
|
||||
return false;
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Action.cast.spell);
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Action.cast.spell, Difficulty.None);
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffects())
|
||||
{
|
||||
if (effect != null && (effect.IsEffect(SpellEffectName.KillCredit) || effect.IsEffect(SpellEffectName.KillCredit2)))
|
||||
{
|
||||
@@ -1437,7 +1446,7 @@ namespace Game.AI
|
||||
}
|
||||
bool IsSpellValid(SmartScriptHolder e, uint entry)
|
||||
{
|
||||
if (!Global.SpellMgr.HasSpellInfo(entry))
|
||||
if (!Global.SpellMgr.HasSpellInfo(entry, Difficulty.None))
|
||||
{
|
||||
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Entry {0} SourceType {1} Event {2} Action {3} uses non-existent Spell entry {4}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
|
||||
return false;
|
||||
@@ -1599,7 +1608,7 @@ namespace Game.AI
|
||||
{ SmartEvents.PassengerRemoved, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.Charmed, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.CharmedTarget, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.SpellhitTarget, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.SpellHitTarget, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.Damaged, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.DamagedTarget, SmartScriptTypeMaskId.Creature },
|
||||
{ SmartEvents.Movementinform, SmartScriptTypeMaskId.Creature },
|
||||
|
||||
@@ -501,7 +501,7 @@ namespace Game.AI
|
||||
// unless target is outside spell range, out of mana, or LOS.
|
||||
|
||||
bool _allowMove = false;
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Action.cast.spell);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(e.Action.cast.spell, me.GetMap().GetDifficultyID());
|
||||
var costs = spellInfo.CalcPowerCost(me, spellInfo.GetSchoolMask());
|
||||
bool hasPower = true;
|
||||
foreach (var cost in costs)
|
||||
@@ -3438,7 +3438,7 @@ namespace Game.AI
|
||||
RecalcTimer(e, e.Event.kill.cooldownMin, e.Event.kill.cooldownMax);
|
||||
break;
|
||||
}
|
||||
case SmartEvents.SpellhitTarget:
|
||||
case SmartEvents.SpellHitTarget:
|
||||
case SmartEvents.SpellHit:
|
||||
{
|
||||
if (spell == null)
|
||||
|
||||
Reference in New Issue
Block a user