fix: Adds guard for monster ability recursion (#2363)

This commit is contained in:
Kamron Batman 2026-03-12 19:26:49 -07:00 committed by GitHub
parent 6b6cc10771
commit 55fe688eaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 20 deletions

View file

@ -27,7 +27,7 @@ public abstract class AreaEffectMonsterAbility : MonsterAbility
protected virtual bool CanEffectTarget(BaseCreature source, Mobile defender) =>
source != defender && defender.Alive && source.CanBeHarmful(defender)
&& (defender.Player || defender is BaseCreature bc && (bc.Team == source.Team || bc.Controlled || bc.Summoned))
&& (defender.Player || defender is BaseCreature bc && (bc.Team != source.Team || bc.Controlled || bc.Summoned))
&& (!Core.AOS || source.InLOS(defender));
protected abstract void DoEffectTarget(BaseCreature source, Mobile defender);

View file

@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System;
namespace Server.Mobiles;
public class DeathExplosion : AreaEffectMonsterAbility
{
private static HashSet<Mobile> _exploding = new();
private static int _chainDepth;
public override MonsterAbilityTrigger AbilityTrigger => MonsterAbilityTrigger.Death;
public override MonsterAbilityType AbilityType => MonsterAbilityType.DeathExplosion;
@ -18,22 +17,25 @@ public class DeathExplosion : AreaEffectMonsterAbility
public override void Trigger(MonsterAbilityTrigger trigger, BaseCreature source, Mobile target)
{
if (trigger != MonsterAbilityTrigger.Death)
if (trigger != MonsterAbilityTrigger.Death || _chainDepth > 0)
{
return;
}
_exploding.Add(source);
source.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
source.PlaySound(0x307);
base.Trigger(trigger, source, target);
_exploding.Remove(source);
_chainDepth++;
try
{
base.Trigger(trigger, source, target);
}
finally
{
_chainDepth--;
}
}
protected override bool CanEffectTarget(BaseCreature source, Mobile defender) =>
!_exploding.Contains(defender) && base.CanEffectTarget(source, defender);
protected override void DoEffectTarget(BaseCreature source, Mobile defender)
{
source.DoHarmful(defender);

View file

@ -1130,6 +1130,8 @@ namespace Server.Mobiles
public virtual MonsterAbility[] GetMonsterAbilities() => null;
private MonsterAbilityTrigger _activeTriggers;
public virtual MonsterAbility GetAbility(MonsterAbilityType type)
{
var abilities = GetMonsterAbilities();
@ -1186,6 +1188,11 @@ namespace Server.Mobiles
public virtual bool TriggerAbility(MonsterAbilityTrigger trigger, Mobile defender)
{
if ((_activeTriggers & trigger) != 0)
{
return false;
}
var abilities = GetMonsterAbilities();
if (abilities == null)
@ -1193,18 +1200,26 @@ namespace Server.Mobiles
return false;
}
var triggered = false;
for (var i = 0; i < abilities.Length; i++)
_activeTriggers |= trigger;
try
{
var ability = abilities[i];
if (ability.CanTrigger(this, trigger))
var triggered = false;
for (var i = 0; i < abilities.Length; i++)
{
ability.Trigger(trigger, this, defender);
triggered = true;
var ability = abilities[i];
if (ability.CanTrigger(this, trigger))
{
ability.Trigger(trigger, this, defender);
triggered = true;
}
}
}
return triggered;
return triggered;
}
finally
{
_activeTriggers &= ~trigger;
}
}
public virtual void TriggerAbilityMove(MonsterAbilityTrigger trigger, Mobile defender, Direction d)