public override void Process(CmdTrigger<RealmServerCmdArgs> trigger) { var spellId = trigger.Text.NextEnum(SpellId.None); var radius = trigger.Text.NextFloat(5); var scale = trigger.Text.NextFloat(1); var dynObj = new DynamicObject(trigger.Args.Character, spellId, radius, trigger.Args.Target.Map, trigger.Args.Target.Position) { ScaleX = scale }; SpellHandler.StaticDOs.Add(dynObj.EntityId, dynObj); trigger.Reply("DynamicObject created."); }
/// <summary> /// Validates targets and applies all SpellEffects /// </summary> public SpellFailedReason Impact() { if (!IsCasting) { return SpellFailedReason.Ok; } // apply effects foreach (var handler in Handlers) { if (handler.Effect.IsPeriodic || handler.Effect.IsStrikeEffect) { // weapon ability or handled by Aura or Channel continue; } handler.Apply(); if (!IsCasting) { // the last handler cancelled the SpellCast return SpellFailedReason.DontReport; } } if (CasterObject is Unit && Spell.IsPhysicalAbility) { // strike at everyone foreach (var target in UnitTargets) { ProcHitFlags hitFlags = CasterUnit.Strike(GetWeapon(), target, this); m_hitInfoByTarget[target] = hitFlags; } } // open Channel and spawn DynamicObject DynamicObject dynObj = null; if (Spell.DOEffect != null) { dynObj = new DynamicObject(this, Spell.DOEffect.GetRadius(CasterReference)); } if (!IsCasting) { return SpellFailedReason.Ok; } List<MissedTarget> missedTargets = null; // create auras List<IAura> auras = null; if (m_auraApplicationInfos != null) { CreateAuras(ref missedTargets, ref auras, dynObj); } // check for missed targets if (missedTargets != null) { if (missedTargets.Count > 0) { // TODO: Flash message ontop of missed heads when impact is delayed CombatLogHandler.SendSpellMiss(this, true, missedTargets); missedTargets.Clear(); } CastMissListPool.Recycle(missedTargets); } // open channel if (Spell.IsChanneled && CasterObject != null) { Channel = SpellChannel.SpellChannelPool.Obtain(); Channel.m_cast = this; if (CasterObject is Unit) { if (dynObj != null) { CasterUnit.ChannelObject = dynObj; } else if (Selected != null) { CasterUnit.ChannelObject = Selected; if (Selected is NPC && Spell.IsTame) { ((NPC)Selected).CurrentTamer = CasterObject as Character; } } } var len = Handlers.Length; var channelEffectHandlers = SpellEffectHandlerListPool.Obtain(); //var channelEffectHandlers = new List<SpellEffectHandler>(6); for (var i = 0; i < len; i++) { var handler = Handlers[i]; if (handler.Effect.IsPeriodic) { channelEffectHandlers.Add(handler); } } Channel.Open(channelEffectHandlers, auras); } // start Auras if (auras != null) { for (var i = 0; i < auras.Count; i++) { var aura = auras[i]; aura.Start(Spell.IsChanneled ? Channel : null, false); } if (!IsChanneling) { auras.Clear(); AuraListPool.Recycle(auras); auras = null; } } // applying debuffs might cancel other Auras if (Spell.HasHarmfulEffects && !Spell.IsPreventionDebuff) { foreach (var target in Targets) { if (target is Unit && Spell.IsHarmfulFor(CasterReference, target)) { ((Unit)target).Auras.RemoveByFlag(AuraInterruptFlags.OnHostileSpellInflicted); } } } //if (CasterChar != null) //{ // CasterChar.SendSystemMessage("SpellCast (Impact): {0} ms", sw1.ElapsedTicks / 10000d); //} return SpellFailedReason.Ok; }
/// <summary> /// Sets the Character's selected GameObject /// </summary> internal GameObject this[Character chr] { get { return chr.ExtraInfo.SelectedGO; } set { var info = chr.ExtraInfo; Deselect(info); if (value != null) { var selection = new GOSelection(value); if (MarkerId != SpellId.None) { var marker = new DynamicObject(chr, MarkerId, MarkerRadius, value.Map, value.Position); selection.Marker = marker; } info.m_goSelection = selection; } } }
public void Dispose() { GO = null; if (Marker != null) { Marker.Delete(); Marker = null; } }
void CreateAuras(ref List<CastMiss> missedTargets, ref List<IAura> auras, DynamicObject dynObj) { auras = AuraListPool.Obtain(); var allowDead = m_spell.PersistsThroughDeath; // create AreaAura if (m_spell.IsAreaAura) { if (dynObj != null || (CasterObject != null && (allowDead || !(CasterObject is Unit) || ((Unit)CasterObject).IsAlive))) { // AreaAura is created at the target location if it is a DynamicObject, else its applied to the caster var aaura = new AreaAura(dynObj ?? CasterObject, m_spell); if (dynObj != null) { // also start the area aura auras.Add(aaura); } // else: Is coupled to an Aura instance } else { LogManager.GetCurrentClassLogger().Warn( "Tried to cast Spell {0} with invalid dynObj or Caster - dynObj: {1}, CasterObject: {2}, CasterUnit: {3}", m_spell, dynObj, CasterObject, CasterUnit); } } // remove missed targets for (var i = m_auraApplicationInfos.Count - 1; i >= 0; i--) { var app = m_auraApplicationInfos[i]; if (!m_targets.Contains(app.Target)) { m_auraApplicationInfos.RemoveAt(i); } } if (m_auraApplicationInfos.Count == 0) { return; } // create Aura-Handlers for (var i = 0; i < m_handlers.Length; i++) { var spellHandler = m_handlers[i]; if (spellHandler is ApplyAuraEffectHandler) { ((ApplyAuraEffectHandler)spellHandler).AddAuraHandlers(m_auraApplicationInfos); } } if (missedTargets == null) { missedTargets = CastMissListPool.Obtain(); } // apply all new Auras for (var i = 0; i < m_auraApplicationInfos.Count; i++) { var info = m_auraApplicationInfos[i]; var target = info.Target; if (!target.IsInContext) { continue; } if (info.Handlers == null || (!allowDead && !target.IsAlive)) { continue; } // check for immunities and resistances CastMissReason missReason; var hostile = m_spell.IsHarmfulFor(CasterReference, target); if (!IsPassive && !m_spell.IsPreventionDebuff && (missReason = CheckDebuffResist(target, m_spell, CasterReference.Level, hostile)) != CastMissReason.None) { // debuff miss missedTargets.Add(new CastMiss(target, missReason)); } else { // create aura var newAura = target.Auras.CreateAura(CasterReference, m_spell, info.Handlers, UsedItem, !m_spell.IsPreventionDebuff && !hostile); if (newAura != null) { // check for debuff if (!m_spell.IsPreventionDebuff && hostile && target.IsInWorld && target.IsAlive) { // force combat mode target.IsInCombat = true; } // add Aura now auras.Add(newAura); } } } //m_auraApplicationInfos.Clear(); //AuraAppListPool.Recycle(m_auraApplicationInfos); m_auraApplicationInfos = null; }
/// <summary> /// Validates targets and applies all SpellEffects /// </summary> public SpellFailedReason Impact(bool delayed) { if (!m_casting || !Caster.IsInWorld) { return SpellFailedReason.Ok; } // figure out whether targets are still valid if delayed List<CastMiss> missedTargets; if (delayed) { missedTargets = CheckHit(m_spell); } else { missedTargets = null; } // apply effects foreach (var handler in m_handlers) { if (handler.Effect.IsPeriodic || handler.Effect.IsStrikeEffect) { // weapon ability or handled by Aura or Channel continue; } handler.Apply(); if (!m_casting) { // the last handler cancelled the SpellCast return SpellFailedReason.DontReport; } } // open Channel and spawn DynamicObject DynamicObject dynObj = null; if (m_spell.DOEffect != null) { dynObj = new DynamicObject(this, m_spell.DOEffect.GetRadius(Caster)); } if (!m_casting) { return SpellFailedReason.Ok; } // create auras List<IAura> auras = null; if (m_auraApplicationInfos != null) { CreateAuras(ref missedTargets, ref auras, dynObj); } // check for missed targets if (missedTargets != null) { if (missedTargets.Count > 0) { // TODO: Flash message ontop of missed heads when impact is delayed CombatLogHandler.SendSpellMiss(m_spell.SpellId, Caster, true, missedTargets); } missedTargets.Clear(); CastMissListPool.Recycle(missedTargets); } // channeling if (m_spell.IsChanneled) { m_channel = SpellChannel.SpellChannelPool.Obtain(); m_channel.m_cast = this; if (Caster is Unit) { if (dynObj != null) { CasterUnit.ChannelObject = dynObj; } else if (Selected != null) { CasterUnit.ChannelObject = Selected; if (Selected is NPC && m_spell.IsTame) { ((NPC)Selected).CurrentTamer = Caster as Character; } } } var len = m_handlers.Length; var channelEffectHandlers = SpellEffectHandlerListPool.Obtain(); //var channelEffectHandlers = new List<SpellEffectHandler>(6); for (var i = 0; i < len; i++) { var handler = m_handlers[i]; if (handler.Effect.IsPeriodic) { channelEffectHandlers.Add(handler); } } m_channel.Open(channelEffectHandlers, auras); } // start Auras if (auras != null) { for (var i = 0; i < auras.Count; i++) { var aura = auras[i]; aura.Start(m_spell.IsChanneled ? m_channel : null, false); } if (!IsChanneling) { auras.Clear(); AuraListPool.Recycle(auras); } } // applying debuffs might cancel other Auras if (m_spell.HasHarmfulEffects && !m_spell.IsPreventionDebuff) { foreach (var target in m_targets) { if (target is Unit && m_spell.IsHarmfulFor(Caster, target)) { ((Unit)target).Auras.RemoveByFlag(AuraInterruptFlags.OnHostileSpellInflicted); } } } // check for weapon abilities if (m_spell.IsPhysicalAbility && !IsChanneling) { if (Caster is Unit) { if (m_spell.IsRangedAbility) { // reset SpellCast so it cannot be cancelled anymore CasterUnit.SpellCast = null; CasterUnit.m_pendingCombatAbility = this; CasterUnit.Strike(GetWeapon()); } if (!IsChanneling) { OnCasted(); } } } //if (CasterChar != null) //{ // CasterChar.SendSystemMessage("SpellCast (Impact): {0} ms", sw1.ElapsedTicks / 10000d); //} // clean it up if ((delayed || m_spell.IsPhysicalAbility) && (!m_spell.IsChanneled) && m_casting) { Cleanup(true); } return SpellFailedReason.Ok; }
public override void Process(CmdTrigger<RealmServerCmdArgs> trigger) { Dictionary<DynamicObject, GameObject> highlighters; var exists = Highlighters.TryGetValue(trigger.Args.Character, out highlighters); var create = trigger.Text.NextBool() || (!trigger.Text.HasNext && !exists); if (!create) { if (exists) { foreach (var dynObj in highlighters.Keys) { dynObj.Delete(); } highlighters.Clear(); Highlighters.Remove(trigger.Args.Character); } trigger.Reply("GO Highlighters OFF"); } else { if (!exists) { Highlighters.Add(trigger.Args.Character, highlighters = new Dictionary<DynamicObject, GameObject>()); } else { foreach (var dynObj in highlighters.Keys) { dynObj.Delete(); } highlighters.Clear(); } var caster = trigger.Args.Character; var gos = caster.GetObjectsInRadius(50f, ObjectTypes.GameObject, false, 0); foreach (GameObject go in gos) { var region = go.Region; var pos = go.Position; pos.Z += 7 * go.ScaleX; // make it appear above the object var dO = new DynamicObject(caster, SpellId.ABOUTTOSPAWN, 5, region, pos); highlighters.Add(dO, go); } trigger.Reply("Highlighting {0} GameObjects", highlighters.Count); } }
/// <summary> /// Sets the Character's selected GameObject /// </summary> internal GameObject this[Character chr] { get { return chr.ExtraInfo.SelectedGO; } set { var info = chr.ExtraInfo; Deselect(info); if (value != null) { var selection = new GOSelection(value); if (MarkerId != SpellId.None) { var marker = new DynamicObject(chr, MarkerId, MarkerRadius, value.Map, value.Position); selection.Marker = marker; // also delete marker marker.CallPeriodically(2000, obj => { if (!chr.IsInWorld || chr.Map != marker.Map || selection.GO == null || !selection.GO.IsInWorld) { marker.Delete(); } }); } info.m_goSelection = selection; } } }
public void Dispose() { GO = null; var marker = Marker; if (marker != null) { marker.Delete(); Marker = null; } }
void CreateAuras(ref List<CastMiss> missedTargets, ref List<IAura> auras, DynamicObject dynObj) { auras = AuraListPool.Obtain(); var allowDead = m_spell.PersistsThroughDeath; // create AreaAura if (m_spell.IsAreaAura) { if (allowDead || !(Caster is Unit) || ((Unit)Caster).IsAlive) { // AreaAura is created at the target location if it is a DynamicObject, else its applied to the caster var areaAura = new AreaAura(dynObj ?? Caster, m_spell); auras.Add(areaAura); } } // remove missed targets for (var i = m_auraApplicationInfos.Count-1; i >= 0; i--) { var app = m_auraApplicationInfos[i]; if (!m_targets.Contains(app.Target)) { m_auraApplicationInfos.RemoveAt(i); } } if (m_auraApplicationInfos.Count == 0) { return; } // create Aura-Handlers for (var i = 0; i < m_handlers.Length; i++) { var spellHandler = m_handlers[i]; if (spellHandler is ApplyAuraEffectHandler) { ((ApplyAuraEffectHandler) spellHandler).AddAuraHandlers(m_auraApplicationInfos); } } if (missedTargets == null) { missedTargets = CastMissListPool.Obtain(); } // apply all new Auras for (var i = 0; i < m_auraApplicationInfos.Count; i++) { var info = m_auraApplicationInfos[i]; var target = info.Target; if (info.Handlers == null || (!allowDead && !target.IsAlive)) { continue; } // check for immunities and resistances CastMissReason missReason; var hostile = m_spell.IsHarmfulFor(Caster, target); var casterInfo = Caster.CasterInfo; if (!IsPassive && !m_spell.IsPreventionDebuff && (missReason = CheckDebuffResist(target, m_spell, casterInfo.Level, hostile)) != CastMissReason.None) { missedTargets.Add(new CastMiss(target, missReason)); } else { var newAura = target.Auras.AddAura(casterInfo, m_spell, info.Handlers, !m_spell.IsPreventionDebuff && !hostile); if (newAura != null) { auras.Add(newAura); // check for debuff if (!m_spell.IsPreventionDebuff && hostile && target.IsInWorld) { // trigger Debuff event target.OnDebuff(this, newAura); } } } } //m_auraApplicationInfos.Clear(); //AuraAppListPool.Recycle(m_auraApplicationInfos); m_auraApplicationInfos = null; }