diff --git a/GameServer/ECS-Effects/AmnesiaECSEffect.cs b/GameServer/ECS-Effects/AmnesiaECSEffect.cs index 4c7dffdb88..a517be6a3a 100644 --- a/GameServer/ECS-Effects/AmnesiaECSEffect.cs +++ b/GameServer/ECS-Effects/AmnesiaECSEffect.cs @@ -1,15 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DOL.GS +namespace DOL.GS { public class AmnesiaECSEffect : ECSGameSpellEffect { - public AmnesiaECSEffect(ECSGameEffectInitParams initParams) - : base(initParams) { } + public AmnesiaECSEffect(ECSGameEffectInitParams initParams) : base(initParams) { } public override void OnStartEffect() { diff --git a/GameServer/ai/brain/StandardMob/StandardMobBrain.cs b/GameServer/ai/brain/StandardMob/StandardMobBrain.cs index f08986bdce..ba5a467b9b 100644 --- a/GameServer/ai/brain/StandardMob/StandardMobBrain.cs +++ b/GameServer/ai/brain/StandardMob/StandardMobBrain.cs @@ -589,13 +589,11 @@ public virtual bool CanAggroTarget(GameLiving target) public virtual void OnAttackedByEnemy(AttackData ad) { - if (!Body.IsAlive || Body.ObjectState != GameObject.eObjectState.Active) + if (!Body.IsAlive || Body.ObjectState != GameObject.eObjectState.Active || FSM.GetCurrentState() == FSM.GetState(eFSMStateType.PASSIVE)) return; - if (FSM.GetCurrentState() == FSM.GetState(eFSMStateType.PASSIVE)) - return; - - ConvertDamageToAggroAmount(ad.Attacker, Math.Max(1, ad.Damage + ad.CriticalDamage)); + if (ad.GeneratesAggro) + ConvertDamageToAggroAmount(ad.Attacker, Math.Max(1, ad.Damage + ad.CriticalDamage)); if (FSM.GetCurrentState() != FSM.GetState(eFSMStateType.AGGRO) && HasAggro) { diff --git a/GameServer/gameutils/AttackData.cs b/GameServer/gameutils/AttackData.cs index 6085520450..b95d8b4422 100644 --- a/GameServer/gameutils/AttackData.cs +++ b/GameServer/gameutils/AttackData.cs @@ -316,5 +316,7 @@ public bool CausesCombat get { return m_causesCombat; } set { m_causesCombat = value; } } + + public bool GeneratesAggro => SpellHandler == null || SpellHandler.Spell.SpellType is not eSpellType.Amnesia || IsSpellResisted; } } diff --git a/GameServer/spells/AmnesiaSpellHandler.cs b/GameServer/spells/AmnesiaSpellHandler.cs index f99d75bc95..d95c639c55 100644 --- a/GameServer/spells/AmnesiaSpellHandler.cs +++ b/GameServer/spells/AmnesiaSpellHandler.cs @@ -1,152 +1,61 @@ -using DOL.AI.Brain; using DOL.GS.PacketHandler; using DOL.Language; namespace DOL.GS.Spells { - [SpellHandlerAttribute("Amnesia")] - public class AmnesiaSpellHandler : SpellHandler - { - public override ECSGameSpellEffect CreateECSEffect(ECSGameEffectInitParams initParams) - { - return new AmnesiaECSEffect(initParams); - } - - /// - /// Execute direct damage spell - /// - /// - public override void FinishSpellCast(GameLiving target) - { - m_caster.Mana -= PowerCost(target); - base.FinishSpellCast(target); - } - - public override void OnDirectEffect(GameLiving target) - { - base.OnDirectEffect(target); - if (target == null || !target.IsAlive) - return; - - /// [Atlas - Takii] This is a silly change by a silly person because disallowing Amnesia while MoC'd has never been a thing in this game. - //if (Caster.EffectList.GetOfType() != null) - // return; + [SpellHandlerAttribute("Amnesia")] + public class AmnesiaSpellHandler : SpellHandler + { + public AmnesiaSpellHandler(GameLiving caster, Spell spell, SpellLine line) : base(caster, spell, line) { } + + public override ECSGameSpellEffect CreateECSEffect(ECSGameEffectInitParams initParams) + { + return new AmnesiaECSEffect(initParams); + } + + public override void FinishSpellCast(GameLiving target) + { + m_caster.Mana -= PowerCost(target); + base.FinishSpellCast(target); + } + + public override void OnDirectEffect(GameLiving target) + { + base.OnDirectEffect(target); + + if (target == null || !target.IsAlive) + return; - //have to do it here because OnAttackedByEnemy is not called to not get aggro - //if (target.Realm == 0 || Caster.Realm == 0) - //target.LastAttackedByEnemyTickPvE = GameLoop.GameLoopTime; - //else target.LastAttackedByEnemyTickPvP = GameLoop.GameLoopTime; - SendEffectAnimation(target, 0, false, 1); + SendEffectAnimation(target, 0, false, 1); - if (target is GamePlayer) - { - ((GamePlayer)target).styleComponent.NextCombatStyle = null; - ((GamePlayer)target).styleComponent.NextCombatBackupStyle = null; - } + if (target is GamePlayer player) + { + player.styleComponent.NextCombatStyle = null; + player.styleComponent.NextCombatBackupStyle = null; + } - //Amnesia only affects normal spells and not song activation (still affects pulses from songs though) - if (target.CurrentSpellHandler?.Spell.InstrumentRequirement == 0) - target.castingComponent.ClearUpSpellHandlers(); //stop even if MoC or QC + // Amnesia only affects normal spells and not song activation (still affects pulses from songs though) + if (target.CurrentSpellHandler?.Spell.InstrumentRequirement == 0) + target.castingComponent.ClearUpSpellHandlers(); - target.rangeAttackComponent.AutoFireTarget = null; - //if(target is GamePlayer) - //target.TargetObject = null; + target.rangeAttackComponent.AutoFireTarget = null; if (target is GamePlayer) MessageToLiving(target, LanguageMgr.GetTranslation((target as GamePlayer).Client, "Amnesia.MessageToTarget"), eChatType.CT_Spell); - /* - GameSpellEffect effect; - effect = SpellHandler.FindEffectOnTarget(target, "Mesmerize"); - if (effect != null) - { - effect.Cancel(false); - return; - }*/ - - //Targets next tick for pulsing speed enhancement spell will be skipped. - // if (target.effectListComponent.ContainsEffectForEffectType(eEffect.Pulse)) - // { - // //EffectListService.TryCancelFirstEffectOfTypeOnTarget(target, eEffect.Pulse); - // foreach(ECSGameEffect e in target.effectListComponent.GetAllPulseEffects()) - // { - - // if(e is ECSGameSpellEffect effect && effect.SpellHandler.Spell.SpellType == eSpellType.SpeedEnhancement) - // { - // Console.WriteLine($"effect: {effect} SpellType: {effect.SpellHandler.Spell.SpellType} PulseFreq: {effect.PulseFreq} "); - // if(effect.ExpireTick > GameLoop.GameLoopTime && effect.ExpireTick < (GameLoop.GameLoopTime + 10000)) - // { - // effect.ExpireTick += effect.PulseFreq; - // if(effect.ExpireTick < (GameLoop.GameLoopTime + 10000)) - // effect.ExpireTick += effect.PulseFreq; - - // } - // } - // } - // } - - // //Casters next tick for pulsing speed enhancement spell will be skipped - // if (Caster.effectListComponent.ContainsEffectForEffectType(eEffect.Pulse)) - // { - // //EffectListService.TryCancelFirstEffectOfTypeOnTarget(target, eEffect.Pulse); - // foreach(ECSGameEffect e in Caster.effectListComponent.GetAllPulseEffects()) - // { - - // if(e is ECSGameSpellEffect effect && effect.SpellHandler.Spell.SpellType == eSpellType.SpeedEnhancement) - // { - // Console.WriteLine($"effect: {effect} SpellType: {effect.SpellHandler.Spell.SpellType} PulseFreq: {effect.PulseFreq} Duration: {effect.Duration} "); - - // if(effect.ExpireTick > GameLoop.GameLoopTime && effect.ExpireTick < (GameLoop.GameLoopTime + 10000)) - // { - // effect.ExpireTick += effect.PulseFreq; - // if(effect.ExpireTick < (GameLoop.GameLoopTime + 10000)) - // effect.ExpireTick += effect.PulseFreq; - - // } - // } - // } - // } - - // //Cancel Mez on target if Amnesia hits. - // if (target.effectListComponent.ContainsEffectForEffectType(eEffect.Mez)) - // { - // var effect = EffectListService.GetEffectOnTarget(target, eEffect.Mez); - - // if (effect != null) - // EffectService.RequestImmediateCancelEffect(effect); - // } - - if (target is GameNPC) - { - GameNPC npc = (GameNPC)target; - IOldAggressiveBrain aggroBrain = npc.Brain as IOldAggressiveBrain; - if (aggroBrain != null) - { - if (Util.Chance(Spell.AmnesiaChance) && npc.TargetObject != null && npc.TargetObject is GameLiving living) - { - aggroBrain.ClearAggroList(); - aggroBrain.AddToAggroList(living, 1); - } - - } - } - } - - /// - /// When spell was resisted - /// - /// the target that resisted the spell - protected override void OnSpellResisted(GameLiving target) - { - base.OnSpellResisted(target); - if (Spell.CastTime == 0) - { - // start interrupt even for resisted instant amnesia - target.StartInterruptTimer(target.SpellInterruptDuration, AttackData.eAttackType.Spell, Caster); - } - } - - // constructor - public AmnesiaSpellHandler(GameLiving caster, Spell spell, SpellLine line) : base(caster, spell, line) {} - } + } + + /// + /// When spell was resisted + /// + /// the target that resisted the spell + protected override void OnSpellResisted(GameLiving target) + { + base.OnSpellResisted(target); + + // Start interrupt even for resisted instant amnesia. + if (Spell.CastTime == 0) + target.StartInterruptTimer(target.SpellInterruptDuration, AttackData.eAttackType.Spell, Caster); + } + } } diff --git a/GameServer/spells/SpellHandler.cs b/GameServer/spells/SpellHandler.cs index ee18c7ee93..36bcab2194 100644 --- a/GameServer/spells/SpellHandler.cs +++ b/GameServer/spells/SpellHandler.cs @@ -2324,15 +2324,17 @@ public virtual void ApplyEffectOnTarget(GameLiving target) if (!HasPositiveEffect) { - AttackData ad = new AttackData(); - ad.Attacker = Caster; - ad.Target = target; - ad.AttackType = AttackData.eAttackType.Spell; - ad.SpellHandler = this; - ad.AttackResult = eAttackResult.HitUnstyled; - ad.IsSpellResisted = false; - ad.Damage = (int)Spell.Damage; - ad.DamageType = Spell.DamageType; + AttackData ad = new() + { + Attacker = Caster, + Target = target, + AttackType = AttackData.eAttackType.Spell, + SpellHandler = this, + AttackResult = eAttackResult.HitUnstyled, + IsSpellResisted = false, + Damage = (int) Spell.Damage, + DamageType = Spell.DamageType + }; m_lastAttackData = ad; Caster.OnAttackEnemy(ad); @@ -2340,7 +2342,7 @@ public virtual void ApplyEffectOnTarget(GameLiving target) // Harmful spells that deal no damage (ie. debuffs) should still trigger OnAttackedByEnemy. // Exception for DoTs here since the initial landing of the DoT spell reports 0 damage // and the first tick damage is done by the pulsing effect, which takes care of firing OnAttackedByEnemy. - if (ad.Damage == 0 && ad.SpellHandler.Spell.SpellType != eSpellType.DamageOverTime) + if (ad.Damage == 0 && ad.SpellHandler.Spell.SpellType is not eSpellType.DamageOverTime) target.OnAttackedByEnemy(ad); } }