Merge branch 'SmartSpell' of github.com:CypherCore/CypherCore

This commit is contained in:
hondacrx
2017-07-27 17:31:41 -04:00
8 changed files with 201 additions and 36 deletions
+7 -2
View File
@@ -195,7 +195,11 @@ namespace Framework.Constants
SceneCancel = 80, // none
SceneComplete = 81, // none
End = 82
//New
SpellEffectHit = 82,
SpellEffectHitTarget = 83,
End = 84
}
public enum SmartActions
@@ -358,7 +362,8 @@ namespace Framework.Constants
LootRecipients = 27, // all players that have tagged this creature (for kill credit)
Farthest = 28, // maxDist, playerOnly, isInLos
VehicleAccessory = 29, // seat number (vehicle can target it's own accessory)
SpellTarget = 30,
End = 30
End = 31
}
}
+2
View File
@@ -19,6 +19,8 @@ using Framework.Constants;
using Game.Entities;
using Game.Movement;
using System.Collections.Generic;
using Game.Scripting;
using Game.Spells;
namespace Game.AI
{
+47 -5
View File
@@ -1051,6 +1051,48 @@ namespace Game.AI
SmartScript mScript;
}
public class SmartSpell : SpellScript
{
public override bool Load()
{
mScript.OnInitialize(GetSpell());
scriptHolders = Global.SmartAIMgr.GetScript((int)GetSpellInfo().Id, SmartScriptType.Spell);
return true;
}
void HandleEffectHit(uint effIndex)
{
mScript.ProcessEventsFor(SmartEvents.SpellEffectHit, GetCaster());
}
void HandleEffectHitTarget(uint effIndex)
{
mScript.ProcessEventsFor(SmartEvents.SpellEffectHitTarget);
}
public override void Register()
{
foreach (var holder in scriptHolders)
{
switch (holder.GetEventType())
{
case SmartEvents.SpellEffectHit:
OnEffectHit.Add(new EffectHandler(HandleEffectHit, holder.Event.spell.effIndex, SpellEffectName.ScriptEffect));
OnEffectHit.Add(new EffectHandler(HandleEffectHit, holder.Event.spell.effIndex, SpellEffectName.Dummy));
break;
case SmartEvents.SpellEffectHitTarget:
OnEffectHitTarget.Add(new EffectHandler(HandleEffectHitTarget, holder.Event.spell.effIndex, SpellEffectName.ScriptEffect));
OnEffectHitTarget.Add(new EffectHandler(HandleEffectHitTarget, holder.Event.spell.effIndex, SpellEffectName.Dummy));
break;
}
}
}
List<SmartScriptHolder> scriptHolders = new List<SmartScriptHolder>();
SmartScript mScript = new SmartScript();
}
[Script]
class SmartTrigger : AreaTriggerScript
{
@@ -1063,7 +1105,7 @@ namespace Game.AI
Log.outDebug(LogFilter.ScriptsAi, "AreaTrigger {0} is using SmartTrigger script", trigger.Id);
SmartScript script = new SmartScript();
script.OnInitialize(null, trigger);
script.OnInitialize(trigger);
script.ProcessEventsFor(SmartEvents.AreatriggerOntrigger, player, trigger.Id);
return true;
}
@@ -1077,28 +1119,28 @@ namespace Game.AI
public override void OnSceneStart(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate)
{
SmartScript smartScript = new SmartScript();
smartScript.OnInitialize(null, null, sceneTemplate);
smartScript.OnInitialize(sceneTemplate);
smartScript.ProcessEventsFor(SmartEvents.SceneStart, player);
}
public override void OnSceneTriggerEvent(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate, string triggerName)
{
SmartScript smartScript = new SmartScript();
smartScript.OnInitialize(null, null, sceneTemplate);
smartScript.OnInitialize(sceneTemplate);
smartScript.ProcessEventsFor(SmartEvents.SceneTrigger, player, 0, 0, false, null, null, triggerName);
}
public override void OnSceneCancel(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate)
{
SmartScript smartScript = new SmartScript();
smartScript.OnInitialize(null, null, sceneTemplate);
smartScript.OnInitialize(sceneTemplate);
smartScript.ProcessEventsFor(SmartEvents.SceneCancel, player);
}
public override void OnSceneComplete(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate)
{
SmartScript smartScript = new SmartScript();
smartScript.OnInitialize(null, null, sceneTemplate);
smartScript.OnInitialize(sceneTemplate);
smartScript.ProcessEventsFor(SmartEvents.SceneComplete, player);
}
}
+32 -7
View File
@@ -28,12 +28,19 @@ namespace Game.AI
{
public class SmartAIManager : Singleton<SmartAIManager>
{
SmartAIManager() { }
SmartAIManager()
{
for (byte i = 0; i < (int)SmartScriptType.Max; i++)
mEventMap[i] = new MultiMap<int, SmartScriptHolder>();
}
public void LoadFromDB()
{
uint oldMSTime = Time.GetMSTime();
for (byte i = 0; i < (int)SmartScriptType.Max; i++)
mEventMap[i].Clear(); //Drop Existing SmartAI List
PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.SEL_SMART_SCRIPTS);
SQLResult result = DB.World.Query(stmt);
if (result.IsEmpty())
@@ -93,6 +100,15 @@ namespace Game.AI
}
break;
}
case SmartScriptType.Spell:
{
if (!Global.SpellMgr.HasSpellInfo((uint)temp.entryOrGuid))
{
Log.outError(LogFilter.Sql, "SmartAIMgr.LoadSmartAIFromDB: Scene id ({0}) does not exist, skipped loading.", temp.entryOrGuid);
continue;
}
break;
}
case SmartScriptType.TimedActionlist:
break;//nothing to check, really
default:
@@ -149,15 +165,13 @@ namespace Game.AI
continue;
// creature entry / guid not found in storage, create empty event list for it and increase counters
if (mEventMap[(int)source_type] == null)
mEventMap[(int)source_type] = new MultiMap<int, SmartScriptHolder>();
if (!mEventMap[(int)source_type].ContainsKey(temp.entryOrGuid))
++count;
// store the new event
mEventMap[(uint)source_type].Add(temp.entryOrGuid, temp);
} while (result.NextRow());
mEventMap[(int)source_type].Add(temp.entryOrGuid, temp);
}
while (result.NextRow());
// Post Loading Validation
for (byte i = 0; i < (int)SmartScriptType.Max; ++i)
@@ -318,6 +332,7 @@ namespace Game.AI
case SmartTargets.Stored:
case SmartTargets.LootRecipients:
case SmartTargets.VehicleAccessory:
case SmartTargets.SpellTarget:
break;
default:
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Not handled target_type({0}), Entry {1} SourceType {2} Event {3} Action {4}, skipped.", e.GetTargetType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -689,6 +704,7 @@ namespace Game.AI
case SmartEvents.SceneCancel:
case SmartEvents.SceneComplete:
case SmartEvents.SceneTrigger:
case SmartEvents.SpellEffectHit:
break;
default:
Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: Not handled event_type({0}), Entry {1} SourceType {2} Event {3} Action {4}, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -1512,7 +1528,9 @@ namespace Game.AI
{ SmartEvents.SceneStart, SmartScriptTypeMaskId.Scene },
{ SmartEvents.SceneTrigger, SmartScriptTypeMaskId.Scene },
{ SmartEvents.SceneCancel, SmartScriptTypeMaskId.Scene },
{ SmartEvents.SceneComplete, SmartScriptTypeMaskId.Scene }
{ SmartEvents.SceneComplete, SmartScriptTypeMaskId.Scene },
{ SmartEvents.SpellEffectHit, SmartScriptTypeMaskId.Spell },
{ SmartEvents.SpellEffectHitTarget, SmartScriptTypeMaskId.Spell }
};
}
@@ -1691,6 +1709,9 @@ namespace Game.AI
[FieldOffset(16)]
public Scene scene;
[FieldOffset(16)]
public Spell spell;
[FieldOffset(16)]
public Raw raw;
@@ -1897,6 +1918,10 @@ namespace Game.AI
{
public uint sceneId;
}
public struct Spell
{
public uint effIndex;
}
public struct Raw
{
public uint param1;
+93 -18
View File
@@ -528,9 +528,11 @@ namespace Game.AI
}
else if (go)
go.CastSpell(obj.ToUnit(), e.Action.cast.spell, triggerFlag);
else if (obj != null)
obj.ToUnit().CastSpell(obj.ToUnit(), e.Action.cast.spell);
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_CAST. Creature {0} casts spell {1} on target {2} with castflags {3}",
me.GetGUID().ToString(), e.Action.cast.spell, obj.GetGUID().ToString(), e.Action.cast.castFlags);
//Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_CAST. Creature {0} casts spell {1} on target {2} with castflags {3}",
// me.GetGUID().ToString(), e.Action.cast.spell, obj.GetGUID().ToString(), e.Action.cast.castFlags);
}
else
Log.outDebug(LogFilter.ScriptsAi, "Spell {0} not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: {1} Entry: {2} Type: {3}) already has the aura",
@@ -2850,6 +2852,12 @@ namespace Game.AI
}
break;
}
case SmartTargets.SpellTarget:
{
if (spellTemplate != null)
l.Add(spellTemplate.m_targets.GetUnitTarget());
break;
}
case SmartTargets.Position:
default:
break;
@@ -3428,6 +3436,9 @@ namespace Game.AI
ProcessAction(e, unit, var0, 0, false, null, null, varString);
break;
}
case SmartEvents.SpellEffectHit:
ProcessAction(e, unit, var0);
break;
default:
Log.outError(LogFilter.Sql, "SmartScript.ProcessEvent: Unhandled Event type {0}", e.GetEventType());
break;
@@ -3623,7 +3634,7 @@ namespace Game.AI
}
}
void FillScript(List<SmartScriptHolder> e, WorldObject obj, AreaTriggerRecord at, SceneTemplate scene)
void FillScript(List<SmartScriptHolder> e, WorldObject obj, AreaTriggerRecord at, SceneTemplate scene, Spell spell = null)
{
if (e.Empty())
{
@@ -3633,6 +3644,8 @@ namespace Game.AI
Log.outDebug(LogFilter.ScriptsAi, "SmartScript: EventMap for AreaTrigger {0} is empty but is using SmartScript.", at.Id);
if (scene != null)
Log.outDebug(LogFilter.ScriptsAi, "SmartScript: EventMap for SceneId {0} is empty but is using SmartScript.", scene.SceneId);
if (spell != null)
Log.outDebug(LogFilter.ScriptsAi, "SmartScript: EventMap for SceneId {0} is empty but is using SmartScript.", scene.SceneId);
return;
}
foreach (var holder in e)
@@ -3656,6 +3669,8 @@ namespace Game.AI
Log.outError(LogFilter.Sql, "SmartScript: AreaTrigger {0} has events but no events added to list because of instance flags. NOTE: triggers can not handle any instance flags.", at.Id);
if (mEvents.Empty() && scene != null)
Log.outError(LogFilter.Sql, "SmartScript: SceneId {0} has events but no events added to list because of instance flags. NOTE: scenes can not handle any instance flags.", scene.SceneId);
if (mEvents.Empty() && spell != null)
Log.outError(LogFilter.Sql, "SmartScript: Spell {0} has events but no events added to list because of instance flags. NOTE: scenes can not handle any instance flags.", spell.GetSpellInfo().Id);
}
void GetScript()
@@ -3685,9 +3700,14 @@ namespace Game.AI
e = Global.SmartAIMgr.GetScript((int)sceneTemplate.SceneId, mScriptType);
FillScript(e, null, null, sceneTemplate);
}
else if (spellTemplate != null)
{
e = Global.SmartAIMgr.GetScript((int)spellTemplate.GetSpellInfo().Id, mScriptType);
FillScript(e, null, null, null, spellTemplate);
}
}
public void OnInitialize(WorldObject obj, AreaTriggerRecord at = null, SceneTemplate scene = null)
public void OnInitialize(WorldObject obj)
{
if (obj != null)
{
@@ -3708,21 +3728,9 @@ namespace Game.AI
return;
}
}
else if (at != null)
{
mScriptType = SmartScriptType.AreaTrigger;
trigger = at;
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.OnInitialize: source is AreaTrigger {0}", trigger.Id);
}
else if (scene != null)
{
mScriptType = SmartScriptType.Scene;
sceneTemplate = scene;
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.OnInitialize: source is Scene with id {0}", scene.SceneId);
}
else
{
Log.outError(LogFilter.ScriptsAi, "SmartScript.OnInitialize: !WARNING! Initialized objects are Null.");
Log.outError(LogFilter.ScriptsAi, "SmartScript.OnInitialize: !WARNING! Initialized WorldObject is Null.");
return;
}
@@ -3736,6 +3744,72 @@ namespace Game.AI
ProcessEventsFor(SmartEvents.JustCreated);
}
public void OnInitialize(AreaTriggerRecord at)
{
if (at != null)
{
mScriptType = SmartScriptType.AreaTrigger;
trigger = at;
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.OnInitialize: AreaTrigger {0}", trigger.Id);
}
else
{
Log.outError(LogFilter.ScriptsAi, "SmartScript.OnInitialize: !WARNING! Initialized AreaTrigger is Null.");
return;
}
GetScript();//load copy of script
foreach (var holder in mEvents)
InitTimer(holder);//calculate timers for first time use
InstallEvents();
}
public void OnInitialize(SceneTemplate scene)
{
if (scene != null)
{
mScriptType = SmartScriptType.Scene;
sceneTemplate = scene;
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.OnInitialize: Scene with id {0}", scene.SceneId);
}
else
{
Log.outError(LogFilter.ScriptsAi, "SmartScript.OnInitialize: !WARNING! Initialized Scene is Null.");
return;
}
GetScript();//load copy of script
foreach (var holder in mEvents)
InitTimer(holder);//calculate timers for first time use
InstallEvents();
}
public void OnInitialize(Spell spell)
{
if (spell != null)
{
mScriptType = SmartScriptType.Spell;
spellTemplate = spell;
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.OnInitialize: Spell id {0}", spell.GetSpellInfo().Id);
}
else
{
Log.outError(LogFilter.ScriptsAi, "SmartScript.OnInitialize: !WARNING! Initialized Spell is Null.");
return;
}
GetScript();//load copy of script
foreach (var holder in mEvents)
InitTimer(holder);//calculate timers for first time use
InstallEvents();
}
public void OnMoveInLineOfSight(Unit who)
{
ProcessEventsFor(SmartEvents.OocLos, who);
@@ -3847,7 +3921,7 @@ namespace Game.AI
return summoner;
}
bool IsUnit(WorldObject obj) { return obj != null && obj.IsTypeId(TypeId.Unit) || obj.IsTypeId(TypeId.Player); }
bool IsUnit(WorldObject obj) { return obj != null && (obj.IsTypeId(TypeId.Unit) || obj.IsTypeId(TypeId.Player)); }
public bool IsPlayer(WorldObject obj) { return obj != null && obj.IsTypeId(TypeId.Player); }
bool IsCreature(WorldObject obj) { return obj != null && obj.IsTypeId(TypeId.Unit); }
static bool IsCreatureInControlOfSelf(WorldObject obj)
@@ -4039,6 +4113,7 @@ namespace Game.AI
ObjectGuid goOrigGUID;
AreaTriggerRecord trigger;
SceneTemplate sceneTemplate;
Spell spellTemplate;
SmartScriptType mScriptType;
uint mEventPhase;
+1 -1
View File
@@ -785,7 +785,7 @@ namespace Game
LoadAutobroadcasts();
// Load and initialize scripts
Global.ObjectMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
//Global.ObjectMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
Global.ObjectMgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
Global.ObjectMgr.LoadWaypointScripts();
+1 -1
View File
@@ -1823,7 +1823,7 @@ namespace Game.Spells
public void LoadScripts()
{
m_loadedScripts = Global.ScriptMgr.CreateAuraScripts(m_spellInfo.Id, this);
foreach (var script in m_loadedScripts.ToList())
foreach (var script in m_loadedScripts)
{
Log.outDebug(LogFilter.Spells, "Aura.LoadScripts: Script `{0}` for aura `{1}` is loaded now", script._GetScriptName(), m_spellInfo.Id);
script.Register();
+18 -2
View File
@@ -32,6 +32,7 @@ using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.InteropServices;
using Game.AI;
namespace Game.Spells
{
@@ -131,7 +132,7 @@ namespace Game.Spells
public virtual void Dispose()
{
// unload scripts
foreach (var script in m_loadedScripts)
foreach (var script in m_loadedScripts.ToList())
script._Unload();
if (m_referencedFromCurrentSpell && m_selfContainer && m_selfContainer == this)
@@ -6646,11 +6647,25 @@ namespace Game.Spells
void LoadScripts()
{
m_loadedScripts = Global.ScriptMgr.CreateSpellScripts(m_spellInfo.Id, this);
var holder = Global.SmartAIMgr.GetScript((int)GetSpellInfo().Id, SmartScriptType.Spell);
if (!holder.Empty())
{
var script = new SmartSpell();
script._Init("", GetSpellInfo().Id);
if (script._Load(this))
{
script._Register();
if (script._Validate(GetSpellInfo()))
m_loadedScripts.Add(script);
}
}
foreach (var script in m_loadedScripts)
{
Log.outDebug(LogFilter.Spells, "Spell.LoadScripts: Script `{0}` for spell `{1}` is loaded now", script._GetScriptName(), m_spellInfo.Id);
script.Register();
}
}
}
void CallScriptBeforeCastHandlers()
@@ -6721,6 +6736,7 @@ namespace Game.Spells
{
// execute script effect handler hooks and check if effects was prevented
bool preventDefault = false;
foreach (var script in m_loadedScripts)
{
SpellScriptHookType hookType;