Aller au contenu

Photo

Still having trouble with a script


  • Veuillez vous connecter pour répondre
22 réponses à ce sujet

#1
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

This is a spell/spirit script thatis supposed to partialy heal and remove all harmful conditions from all alies within the effect radius.  There seems to be an on-going problem with it as it only affects a few of the ally targets within the spell's range rather than all.  I was wondering is someone could take a final look at it to see what is still wrong.  It tests it has been cast by hired companions rather than the player character if that makes a difference.  Here is the spell script, thanking everyone in advance;

 

#include "nw_i0_spells" 
#include "nwn2_inc_spells"
#include "x2_inc_spellhook"
const int SPIRIT_ANCIENT = 1612;
 
int kL_GetIsEffectBad(effect eEffect);
 
 
 
void main()
{
    if (!X2PreSpellCastCode())
    {
// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }
 
    object oCaster = OBJECT_SELF;// = ; defn
    location lCaster = GetLocation(oCaster);
    effect eEffect;
int iCasterLvl = GetLevelByClass(64, OBJECT_SELF);
int iHeal = (iCasterLvl/4);
int iHeal1 = d8(iHeal);
effect eVis = EffectVisualEffect( VFX_IMP_HEALING_M );
effect eHeal2 = EffectHeal((iHeal1)+(iCasterLvl*2));
eHeal2 = SupernaturalEffect(eHeal2);
 
    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster); // 10' circle
    while (GetIsObjectValid(oTarget))
    {
        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
        {
            eEffect = GetFirstEffect(oTarget);
            while (GetIsEffectValid(eEffect))
            {
                if (kL_GetIsEffectBad(eEffect))
                {
                    RemoveEffect(oTarget, eEffect);
                    eEffect = GetFirstEffect(oTarget); // remove linked effects safely.
}
                else
                    eEffect = GetNextEffect(oTarget);
            }
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHeal2, oTarget);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
        }
 
        oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster);
    }
}
 
// Returns TRUE if an effect is bad.
int kL_GetIsEffectBad(effect eEffect)
{
    int iType = GetEffectType(eEffect);
    if (iType == EFFECT_TYPE_ABILITY_DECREASE
            || iType == EFFECT_TYPE_AC_DECREASE
            || iType == EFFECT_TYPE_ARCANE_SPELL_FAILURE
            || iType == EFFECT_TYPE_AMORPENALTYINC
            || iType == EFFECT_TYPE_ATTACK_DECREASE
            || iType == EFFECT_TYPE_BLINDNESS
            || iType == EFFECT_TYPE_CHARMED
            || iType == EFFECT_TYPE_CONCEALMENT_NEGATED
            || iType == EFFECT_TYPE_CONFUSED
            || iType == EFFECT_TYPE_CURSE
            || iType == EFFECT_TYPE_CUTSCENE_PARALYZE
            || iType == EFFECT_TYPE_CUTSCENEGHOST
            || iType == EFFECT_TYPE_CUTSCENEIMMOBILIZE
            || iType == EFFECT_TYPE_DAMAGE_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_REDUCTION_NEGATED
            || iType == EFFECT_TYPE_DARKNESS
            || iType == EFFECT_TYPE_DAZED
            || iType == EFFECT_TYPE_DEAF
            || iType == EFFECT_TYPE_DISEASE
            || iType == EFFECT_TYPE_DOMINATED
            || iType == EFFECT_TYPE_ENEMY_ATTACK_BONUS
            || iType == EFFECT_TYPE_ENTANGLE
            || iType == EFFECT_TYPE_FRIGHTENED
            || iType == EFFECT_TYPE_INSANE
            || iType == EFFECT_TYPE_JARRING
            || iType == EFFECT_TYPE_MESMERIZE
            || iType == EFFECT_TYPE_MISS_CHANCE
            || iType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE
            || iType == EFFECT_TYPE_NEGATIVELEVEL
            || iType == EFFECT_TYPE_PARALYZE
            || iType == EFFECT_TYPE_PETRIFY
            || iType == EFFECT_TYPE_POISON
            || iType == EFFECT_TYPE_POLYMORPH
            || iType == EFFECT_TYPE_SAVING_THROW_DECREASE
            || iType == EFFECT_TYPE_SILENCE
            || iType == EFFECT_TYPE_SKILL_DECREASE
            || iType == EFFECT_TYPE_SLEEP
            || iType == EFFECT_TYPE_SLOW
            || iType == EFFECT_TYPE_SPELL_FAILURE
            || iType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE
            || iType == EFFECT_TYPE_STUNNED
            || iType == EFFECT_TYPE_SWARM
            || iType == EFFECT_TYPE_TURNED
            || iType == EFFECT_TYPE_WOUNDING)
    {
        return TRUE;
    }
 
    return FALSE;
}


#2
kevL

kevL
  • Members
  • 4 052 messages

... it has been cast by hired companions rather than the player character if that makes a difference


try commenting out the spellsIsTarget() check, see if that makes a difference.

//        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))


#3
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

try commenting out the spellsIsTarget() check, see if that makes a difference.
 

//        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))

Do you mean remove it?



#4
kevL

kevL
  • Members
  • 4 052 messages
just comment it out with 2 slashes & compile, then test it IG

#5
kevL

kevL
  • Members
  • 4 052 messages
the extra braces don't hurt, and if the spell works, well i have suspicions ...

#6
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

just comment it out with 2 slashes & compile, then test it IG

So you mean like this? I never heard of the term "comment it out".

 

        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster)) // target only allies



#7
kevL

kevL
  • Members
  • 4 052 messages
to "comment out" or "remark" a line (or more) of code means to make the compiler think it's a comment, so it won't end up as machine code (but it's still available in case you want it back).

normal:
if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
commented:
//if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
(very useful for testing small chunks of code or individual function calls - like spellsIsTarget(), when OBJECT_SELF is a henchman in this case)

#8
The Fred

The Fred
  • Members
  • 2 516 messages

It's been a long time, but isn't heal meant to be an instant effect too? (May not make any difference)



#9
kevL

kevL
  • Members
  • 4 052 messages
hey Fred, good to hear from ya!

itching a scratch?

#10
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

The program compiled when the SpellIsTarget() function was commented out but it still did not work right in play.  (It was healing my enemies as well as my allies.)  However I moved the healing function outside of the SpellIsTarget() function and it does seem to be sort-of working.  I still need to test further.  I hope it does not heal the enemies as well.

 

 #include "nw_i0_spells" 

#include "nwn2_inc_spells"
#include "x2_inc_spellhook"
const int SPIRIT_ANCIENT = 1612;
 
int kL_GetIsEffectBad(effect eEffect);
 
 
 
void main()
{
    if (!X2PreSpellCastCode())
    {
// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }
 
    object oCaster = OBJECT_SELF;// = ; defn
    location lCaster = GetLocation(oCaster);
    effect eEffect;
int iCasterLvl = GetLevelByClass(64, OBJECT_SELF);
int iHeal = (iCasterLvl/4);
int iHeal1 = d8(iHeal);
effect eVis = EffectVisualEffect( VFX_IMP_HEALING_M );
effect eHeal2 = EffectHeal((iHeal1)+(iCasterLvl*2));
eHeal2 = SupernaturalEffect(eHeal2);
 
    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster); // 10' circle
    while (GetIsObjectValid(oTarget))
    {
        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
        {
            eEffect = GetFirstEffect(oTarget);
            while (GetIsEffectValid(eEffect))
            {
                if (kL_GetIsEffectBad(eEffect))
                {
                    RemoveEffect(oTarget, eEffect);
                    eEffect = GetFirstEffect(oTarget); // remove linked effects safely.
}
                else
                    eEffect = GetNextEffect(oTarget);
            }
        }
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHeal2, oTarget);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); 
        oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster);
    }
}
 
// Returns TRUE if an effect is bad.
int kL_GetIsEffectBad(effect eEffect)
{
    int iType = GetEffectType(eEffect);
    if (iType == EFFECT_TYPE_ABILITY_DECREASE
            || iType == EFFECT_TYPE_AC_DECREASE
            || iType == EFFECT_TYPE_ARCANE_SPELL_FAILURE
            || iType == EFFECT_TYPE_AMORPENALTYINC
            || iType == EFFECT_TYPE_ATTACK_DECREASE
            || iType == EFFECT_TYPE_BLINDNESS
            || iType == EFFECT_TYPE_CHARMED
            || iType == EFFECT_TYPE_CONCEALMENT_NEGATED
            || iType == EFFECT_TYPE_CONFUSED
            || iType == EFFECT_TYPE_CURSE
            || iType == EFFECT_TYPE_CUTSCENE_PARALYZE
            || iType == EFFECT_TYPE_CUTSCENEGHOST
            || iType == EFFECT_TYPE_CUTSCENEIMMOBILIZE
            || iType == EFFECT_TYPE_DAMAGE_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_REDUCTION_NEGATED
            || iType == EFFECT_TYPE_DARKNESS
            || iType == EFFECT_TYPE_DAZED
            || iType == EFFECT_TYPE_DEAF
            || iType == EFFECT_TYPE_DISEASE
            || iType == EFFECT_TYPE_DOMINATED
            || iType == EFFECT_TYPE_ENEMY_ATTACK_BONUS
            || iType == EFFECT_TYPE_ENTANGLE
            || iType == EFFECT_TYPE_FRIGHTENED
            || iType == EFFECT_TYPE_INSANE
            || iType == EFFECT_TYPE_JARRING
            || iType == EFFECT_TYPE_MESMERIZE
            || iType == EFFECT_TYPE_MISS_CHANCE
            || iType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE
            || iType == EFFECT_TYPE_NEGATIVELEVEL
            || iType == EFFECT_TYPE_PARALYZE
            || iType == EFFECT_TYPE_PETRIFY
            || iType == EFFECT_TYPE_POISON
            || iType == EFFECT_TYPE_POLYMORPH
            || iType == EFFECT_TYPE_SAVING_THROW_DECREASE
            || iType == EFFECT_TYPE_SILENCE
            || iType == EFFECT_TYPE_SKILL_DECREASE
            || iType == EFFECT_TYPE_SLEEP
            || iType == EFFECT_TYPE_SLOW
            || iType == EFFECT_TYPE_SPELL_FAILURE
            || iType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE
            || iType == EFFECT_TYPE_STUNNED
            || iType == EFFECT_TYPE_SWARM
            || iType == EFFECT_TYPE_TURNED
            || iType == EFFECT_TYPE_WOUNDING)
    {
        return TRUE;
    }
 
    return FALSE;
}
 
Please advise if you can forsee any problems with this possible solution.


#11
kevL

kevL
  • Members
  • 4 052 messages
sorry i should have explained the test better,

yes commenting spellsIsTarget() will cause the spell to hit everyone. But the problem was that the loop appears to be missing or skipping over targets. So, by temporarily removing that line *everyone* *should* get a hit.

1. if they do get a hit, the problem is in spellsIsTarget()
2. if some targets were/are still getting missed, the problem is elsewhere in the loop.
3. ...

does that make sense? To be honest the first version of the script (above) looks really quite good, otherwise, apart from a few niggles here & there.


Please advise if you can forsee any problems with this possible solution.

uh yeah, everyone in-range is going to get a heal!

#12
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

sorry i should have explained the test better,

yes commenting spellsIsTarget() will cause the spell to hit everyone. But the problem was that the loop appears to be missing or skipping over targets. So, by temporarily removing that line *everyone* *should* get a hit.

1. if they do get a hit, the problem is in spellsIsTarget()
2. if some targets were/are still getting missed, the problem is elsewhere in the loop.
3. ...

does that make sense? To be honest the first version of the script (above) looks really quite good, otherwise, apart from a few niggles here & there.


uh yeah, everyone in-range is going to get a heal!

What niggles?  Perhaps one of them is why the spell is not targeting all of allies within range.



#13
kevL

kevL
  • Members
  • 4 052 messages
here's a refactored version of the first script above. It includes debug that should say what creatures are within the AoE and which ones pass the spellsIsTarget() check
 
#include "x2_inc_spellhook"

int kL_GetIsEffectBad(effect eEffect);


void main()
{
    if (!X2PreSpellCastCode())
    {
        // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

    object oCaster = OBJECT_SELF;
    location lCaster = GetLocation(oCaster);

    int iCasterLvl = GetLevelByClass(64, oCaster);
    int iHeal = iCasterLvl / 4;
    effect eHeal = EffectHeal((iCasterLvl * 2) + d8(iHeal)); // d8() gets min. 1 dice (ie. min. 1pt heal)

    effect eVis = EffectVisualEffect(VFX_IMP_HEALING_M);
    effect eEffect;

    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster); // 15' circle
    while (GetIsObjectValid(oTarget))
    {
        SendMessageToPC(GetFirstPC(FALSE), "Target " + GetName(oTarget)); // <- debug
        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
        {
            SendMessageToPC(GetFirstPC(FALSE), ". is Ally"); // <- debug
            eEffect = GetFirstEffect(oTarget);
            while (GetIsEffectValid(eEffect))
            {
                SendMessageToPC(GetFirstPC(FALSE), ". . has effect"); // <- debug
                if (kL_GetIsEffectBad(eEffect))
                {
                    SendMessageToPC(GetFirstPC(FALSE), ". . . effect Bad - REMOVE"); // <- debug
                    RemoveEffect(oTarget, eEffect);
                    eEffect = GetFirstEffect(oTarget); // remove linked effects safely.
                }
                else
                {
                    SendMessageToPC(GetFirstPC(FALSE), ". . . effect next."); // <- debug
                    eEffect = GetNextEffect(oTarget);
                }
            }

            SendMessageToPC(GetFirstPC(FALSE), ". apply Heal"); // <- debug
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
        }
        else SendMessageToPC(GetFirstPC(FALSE), ". is NOT Ally"); // <- debug

        oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster);
    }
}

// Returns TRUE if an effect is bad.
int kL_GetIsEffectBad(effect eEffect)
{
    int iType = GetEffectType(eEffect);
    if (iType == EFFECT_TYPE_ABILITY_DECREASE
            || iType == EFFECT_TYPE_AC_DECREASE
            || iType == EFFECT_TYPE_ARCANE_SPELL_FAILURE
            || iType == EFFECT_TYPE_AMORPENALTYINC
            || iType == EFFECT_TYPE_ATTACK_DECREASE
            || iType == EFFECT_TYPE_BLINDNESS
            || iType == EFFECT_TYPE_CHARMED
            || iType == EFFECT_TYPE_CONCEALMENT_NEGATED
            || iType == EFFECT_TYPE_CONFUSED
            || iType == EFFECT_TYPE_CURSE
            || iType == EFFECT_TYPE_CUTSCENE_PARALYZE
            || iType == EFFECT_TYPE_CUTSCENEGHOST
            || iType == EFFECT_TYPE_CUTSCENEIMMOBILIZE
            || iType == EFFECT_TYPE_DAMAGE_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE
            || iType == EFFECT_TYPE_DAMAGE_REDUCTION_NEGATED
            || iType == EFFECT_TYPE_DARKNESS
            || iType == EFFECT_TYPE_DAZED
            || iType == EFFECT_TYPE_DEAF
            || iType == EFFECT_TYPE_DISEASE
            || iType == EFFECT_TYPE_DOMINATED
            || iType == EFFECT_TYPE_ENEMY_ATTACK_BONUS
            || iType == EFFECT_TYPE_ENTANGLE
            || iType == EFFECT_TYPE_FRIGHTENED
            || iType == EFFECT_TYPE_INSANE
            || iType == EFFECT_TYPE_JARRING
            || iType == EFFECT_TYPE_MESMERIZE
            || iType == EFFECT_TYPE_MISS_CHANCE
            || iType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE
            || iType == EFFECT_TYPE_NEGATIVELEVEL
            || iType == EFFECT_TYPE_PARALYZE
            || iType == EFFECT_TYPE_PETRIFY
            || iType == EFFECT_TYPE_POISON
            || iType == EFFECT_TYPE_POLYMORPH
            || iType == EFFECT_TYPE_SAVING_THROW_DECREASE
            || iType == EFFECT_TYPE_SILENCE
            || iType == EFFECT_TYPE_SKILL_DECREASE
            || iType == EFFECT_TYPE_SLEEP
            || iType == EFFECT_TYPE_SLOW
            || iType == EFFECT_TYPE_SPELL_FAILURE
            || iType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE
            || iType == EFFECT_TYPE_STUNNED
            || iType == EFFECT_TYPE_SWARM
            || iType == EFFECT_TYPE_TURNED
            || iType == EFFECT_TYPE_WOUNDING)
    {
        return TRUE;
    }

    return FALSE;
}


#14
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Thank you,

 

However I am getting an error of no right bracket on line 28.  



#15
kevL

kevL
  • Members
  • 4 052 messages
when i copy-paste it compiles no errors.

#16
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

I got it to compile when I replaced #include "x2_inc_spellhook" at the top with

 

#include "nw_i0_spells" 

#include "nwn2_inc_spells"
#include "x2_inc_spellhook"
const int SPIRIT_ANCIENT = 1612;
 
and it compiled just fine.


#17
kevL

kevL
  • Members
  • 4 052 messages
great. Anything useful from the debug?

#18
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Nothing yet but I am beginning to wonder if it could bea problem with the companion herself.  The spell is firing fine in the 1st area of the campaign but not so wel in theother modules. I beginning to suspect that the kinc_companion script for the modules themselves are causing this character to not recognize her other companions in the roster when casting this spell.  It may not be the spell itself buther relation to others in the party roster.  I will write again after getting some time to test.



#19
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

After testing, I think this may be a memroy issue because it is only happening in certain areas.  In larger areas where there is more going on or larger areas with more involved scenery, it is looping on the first roster companion after the player's character.  It is looping so bad that the debug version revealed an endless loop of it detecting effects that were not there and instead of removing the effect, just looping to the next effect.

To see if I can free-up more memory I am looking into what placeables (if any) can be converted into environmental objects.



#20
kevL

kevL
  • Members
  • 4 052 messages
hm, interesting hypothesis. But is it possible that there really are so many effects on a char, that the engine throws a TMI (too many instructions) and stops the loop prematurely ... in those big areas?

Here's a test script that iterates over all effects on a char -- it doesn't count effects per se, and the output is quite obtuse, but it would give a sense of how many and what effects are on a subject ...

#21
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

hm, interesting hypothesis. But is it possible that there really are so many effects on a char, that the engine throws a TMI (too many instructions) and stops the loop prematurely ... in those big areas?

Here's a test script that iterates over all effects on a char -- it doesn't count effects per se, and the output is quite obtuse, but it would give a sense of how many and what effects are on a subject ...

My memory theory did not pan-out so I tried the script and customizedit so I could cast it upon any companion in my group unfortunately it is not telling me any effects (even the ones I know about) when used.  I made it so it would fire like a feat-based spell during the game.  Is there a specific way you are supposed to fire it in the game?



#22
kevL

kevL
  • Members
  • 4 052 messages
from the console.

Copy it to a subdirectory of /Override, eg. "test_scripts", compile it as testeffect.nss ... and when you're in game RightClick an NPC then invoke it at the console:

`
debugmode 1
rs testeffect(0)


It should list out the effects that the targetted NPC currently has: the numbers correspond to EFFECT_TYPE_* constants, iirc. If you want more detailed data about one of the effects (if any), replace "0" in the command with a number that shows. But i think you want just the basic info on how many (and perhaps what) effects are there. Then you should run and re-run your Feat to see if there's a pattern ...

in fact, in the debug-line of your script ". . has effect" you could also add IntToString(GetEffectType(eEffect)) and those numbers should match, in some way, with the output from the testscript. It's all pretty vague until something stands out

#23
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

Try with this and see if it works:

#include "nw_i0_spells"
#include "nwn2_inc_spells"
#include "x2_inc_spellhook"
const int SPIRIT_ANCIENT = 1612;
 
// Returns TRUE if an effect is bad.
int kL_GetIsEffectBad(effect eEffect)
{
    int iType = GetEffectType(eEffect);
    
    switch(iType)
    {
        case EFFECT_TYPE_AC_DECREASE:
        case EFFECT_TYPE_ARCANE_SPELL_FAILURE:
        case EFFECT_TYPE_AMORPENALTYINC:
        case EFFECT_TYPE_ATTACK_DECREASE:
        case EFFECT_TYPE_BLINDNESS:
        case EFFECT_TYPE_CHARMED:
        case EFFECT_TYPE_CONCEALMENT_NEGATED:
        case EFFECT_TYPE_CONFUSED:
        case EFFECT_TYPE_CURSE:
        case EFFECT_TYPE_CUTSCENE_PARALYZE: //Are you sure about this one?
        case EFFECT_TYPE_CUTSCENEGHOST: //Are you sure about this one?
        case EFFECT_TYPE_CUTSCENEIMMOBILIZE: //Are you sure about this one?
        case EFFECT_TYPE_DAMAGE_DECREASE:
        case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE:
        case EFFECT_TYPE_DAMAGE_REDUCTION_NEGATED:
        case EFFECT_TYPE_DARKNESS:
        case EFFECT_TYPE_DAZED:
        case EFFECT_TYPE_DEAF:
        case EFFECT_TYPE_DISEASE:
        case EFFECT_TYPE_DOMINATED:
        case EFFECT_TYPE_ENEMY_ATTACK_BONUS:
        case EFFECT_TYPE_ENTANGLE:
        case EFFECT_TYPE_FRIGHTENED:
        case EFFECT_TYPE_INSANE:
        case EFFECT_TYPE_JARRING:
        case EFFECT_TYPE_MESMERIZE:
        case EFFECT_TYPE_MISS_CHANCE:
        case EFFECT_TYPE_MOVEMENT_SPEED_DECREASE:
        case EFFECT_TYPE_NEGATIVELEVEL:
        case EFFECT_TYPE_PARALYZE:
        case EFFECT_TYPE_PETRIFY:
        case EFFECT_TYPE_POISON:
        case EFFECT_TYPE_POLYMORPH: // This could also be a positive effect.
        case EFFECT_TYPE_SAVING_THROW_DECREASE:
        case EFFECT_TYPE_SILENCE:
        case EFFECT_TYPE_SKILL_DECREASE:
        case EFFECT_TYPE_SLEEP:
        case EFFECT_TYPE_SLOW:
        case EFFECT_TYPE_SPELL_FAILURE:
        case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE:
        case EFFECT_TYPE_STUNNED:
        case EFFECT_TYPE_SWARM:
        case EFFECT_TYPE_TURNED:
        case EFFECT_TYPE_WOUNDING:
        return TRUE; break;
    }
 
    return FALSE;
}
 

void main()
{
    if (!X2PreSpellCastCode())
    {
        // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

    object oCaster = OBJECT_SELF;// = ; defn
    location lCaster = GetLocation(oCaster);
    effect eEffect;
    int iCasterLvl = GetLevelByClass(64, OBJECT_SELF);
    int iHeal = (iCasterLvl/4);
    int iHeal1 = d8(iHeal);
    effect eVis = EffectVisualEffect( VFX_IMP_HEALING_M );
    effect eHeal2 = EffectHeal((iHeal1)+(iCasterLvl*2));
 
    object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster); // 10' circle
    while (GetIsObjectValid(oTarget))
    {
        if (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
        {
            eEffect = GetFirstEffect(oTarget);
            while (GetIsEffectValid(eEffect))
            {
                if (kL_GetIsEffectBad(eEffect))
                {
                    RemoveEffect(oTarget, eEffect);
                }
                eEffect = GetNextEffect(oTarget);
            }
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal2, oTarget);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
        }
        oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lCaster);
    }
}