public override void OnSpellEffect(SpellPacketBody spell)
    {
        var check = Co8.check_for_protection_from_spells(spell.Targets, 0);

        Logger.Info("Mass Inflict Light Wounds OnSpellEffect");
        var remove_list = new List <GameObject>();
        var dice        = Dice.D8;

        dice = dice.WithModifier(Math.Min(25, spell.casterLevel));
        foreach (var target_item in spell.Targets)
        {
            AttachParticles("sp-Inflict Light Wounds", target_item.Object);
            // hurt enemies, heal undead
            if (target_item.Object.IsMonsterCategory(MonsterCategory.undead))
            {
                // allow Fortitude saving throw for half
                if (target_item.Object.SavingThrowSpell(spell.dc, SavingThrowType.Fortitude, D20SavingThrowFlag.NONE, spell.caster, spell.spellId))
                {
                    // saving throw succesful, damage target, 1/2 damage
                    target_item.Object.FloatMesFileLine("mes/spell.mes", 30001);
                    target_item.Object.HealFromSpell(spell.caster, dice, D20ActionType.CAST_SPELL, spell.spellId);
                }
                else
                {
                    // saving throw unsuccesful, damage target, full damage
                    target_item.Object.FloatMesFileLine("mes/spell.mes", 30002);
                    target_item.Object.HealFromSpell(spell.caster, dice, D20ActionType.CAST_SPELL, spell.spellId);
                }
            }
            else
            {
                // check saving throw, damage target
                if (target_item.Object.SavingThrowSpell(spell.dc, SavingThrowType.Will, D20SavingThrowFlag.NONE, spell.caster, spell.spellId))
                {
                    target_item.Object.FloatMesFileLine("mes/spell.mes", 30001);
                    // saving throw succesful, damage target, 1/2 damage
                    target_item.Object.DealReducedSpellDamage(spell.caster, DamageType.NegativeEnergy, dice, D20AttackPower.UNSPECIFIED, DAMAGE_REDUCTION_HALF, D20ActionType.CAST_SPELL, spell.spellId);
                }
                else
                {
                    target_item.Object.FloatMesFileLine("mes/spell.mes", 30002);
                    // saving throw unsuccesful, damage target, full damage
                    target_item.Object.DealSpellDamage(spell.caster, DamageType.NegativeEnergy, dice, D20AttackPower.UNSPECIFIED, D20ActionType.CAST_SPELL, spell.spellId);
                }
            }

            remove_list.Add(target_item.Object);
        }

        spell.RemoveTargets(remove_list);
        if (check)
        {
            Co8.replace_protection_from_spells();
        }

        spell.EndSpell();
    }