Eruption Spell not working as it should (RESOLVED)

I found a spell called Eruption

The spell casting works the VFX works, but no damage is done. Well tested it on 4 different creatures with no effect.

I looked at the script and the funny thing is…I don’t see initial eruption dealing 12d6 damage as it says in the description below in the spell. Why?

Sorry…cleaning up my spells that don’t work or not working properly. Sorry to bug you guys out there so much with these requests. See spell below…anyone?

//:://////////////////////////////////////////////
/*
// Up to three fiery eruptions occur at the target location
// over the course of one round after casting the spell, each
// spaced 2 seconds apart. The initial eruption deals 12d6 damage
// to creatures within its area of effect, with a Reflex save
// allowed for half damage; if the target fails this save they
// are additionally stunned for one round.
//
// Each subsequent eruption deals half as much damage as the
// previous one and has its DC reduced by 2.
*/
//:://////////////////////////////////////////////

#include "X0_I0_SPELLS"
#include "x2_inc_spellhook"

int nDamage, nDC;
effect eDam, eStun, eVis;

void EruptionGroundVFX(location lLoc)
{
    effect eEruptG = EffectVisualEffect(679); // Ground duration effect
    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eEruptG, lLoc, 12.0);
}

void EruptionVFX(location lLoc)
{
    effect eEruptF = EffectVisualEffect(680); // Eruption FnF effect
    effect eEruptS = EffectVisualEffect(287); // Screen bump effect
    effect eEruptR = EffectVisualEffect(354); // Rock chunk effect

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptR, lLoc);
    DelayCommand(0.1, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptR, lLoc));

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptS, lLoc);

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc);
    DelayCommand(0.15, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc));
    DelayCommand(0.35, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc));
}

void Eruption(location lLoc, int nDamage, int nDC)
{
    EruptionVFX(lLoc);

    object oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, RADIUS_SIZE_LARGE, lLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);

    while(GetIsObjectValid(oTarget))
    {
        float fDelay = GetDistanceBetweenLocations(lLoc, GetLocation(oTarget))/20;

        if(!GetIsReactionTypeFriendly(oTarget))
        {
            if (MyResistSpell(OBJECT_SELF, oTarget, fDelay) <= 0)
            {
            int nReflexCheckHack = GetReflexAdjustedDamage(2, oTarget, nDC, SAVING_THROW_TYPE_FIRE, OBJECT_SELF);

                switch (nReflexCheckHack)
                {
                    case 0: // Evasion/Improved Evasion, or equivalent modifier
                        // Nothing here, resisted all effects
                    break;

                    case 1: // Reflex save: Success
                        nDamage = nDamage /2;
                        eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
                        eVis = EffectVisualEffect(VFX_IMP_FLAME_S);

                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
                    break;

                    case 2: // Reflex save: Failure
                        eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
                        eStun = EffectStunned();
                        eVis = EffectVisualEffect(VFX_IMP_FLAME_M);

                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStun, oTarget, 1.0));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
                    break;
                }
            }
        }
    oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, RADIUS_SIZE_LARGE, lLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
    }
}

void main()
{
    location lLoc = GetSpellTargetLocation();

    EruptionGroundVFX(lLoc);
    DelayCommand(2.0, Eruption(lLoc, d6(12), GetSpellSaveDC()));
    DelayCommand(4.0, Eruption(lLoc, d6(6), GetSpellSaveDC()-2));
    DelayCommand(6.0, Eruption(lLoc, d6(3), GetSpellSaveDC()-4));
}

I guess the “GetReflexAdjustedDamage”-function is not used properly. Why do you assume that it returns 0, 1 or 2? IMO the function returns directly the resulting damage after a reflex throw, so no “switch” necessary.

Dunnno,

I don’t script…I just had this spell for awhile in my mod that I pulled off the vault but it never worked. I’m trying to fix broken spells. This is one I can’t fix or figure out why it is not working.

Can you fix it and upload it here?

Maybe try and add some SendMessageToPC in the script to see if it fires at all, and if so, what sections fire.

1 Like

I’m going to try this bit of debugging script tinygiant puts in his scripts for me to test abvoe the void main

int DEBUG_ME = FALSE;
void debug(object o, string s)
{
    if (DEBUG_ME) SendMessageToPC(o, s);
}

Going to test it now

EDIT: Of course I will change it to: TRUE rather than FALSE

You can’t just write his code like that. You have to put the debug messages into the script too.

Maybe something like this:

//:://////////////////////////////////////////////
/*
// Up to three fiery eruptions occur at the target location
// over the course of one round after casting the spell, each
// spaced 2 seconds apart. The initial eruption deals 12d6 damage
// to creatures within its area of effect, with a Reflex save
// allowed for half damage; if the target fails this save they
// are additionally stunned for one round.
//
// Each subsequent eruption deals half as much damage as the
// previous one and has its DC reduced by 2.
*/
//:://////////////////////////////////////////////

#include "X0_I0_SPELLS"
#include "x2_inc_spellhook"

int nDamage, nDC;
effect eDam, eStun, eVis;

void EruptionGroundVFX(location lLoc)
{
    effect eEruptG = EffectVisualEffect(679); // Ground duration effect
    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eEruptG, lLoc, 12.0);
}

void EruptionVFX(location lLoc)
{
    effect eEruptF = EffectVisualEffect(680); // Eruption FnF effect
    effect eEruptS = EffectVisualEffect(287); // Screen bump effect
    effect eEruptR = EffectVisualEffect(354); // Rock chunk effect

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptR, lLoc);
    DelayCommand(0.1, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptR, lLoc));

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptS, lLoc);

    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc);
    DelayCommand(0.15, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc));
    DelayCommand(0.35, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEruptF, lLoc));
}

void Eruption(location lLoc, int nDamage, int nDC)
{
    EruptionVFX(lLoc);

    object oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, RADIUS_SIZE_LARGE, lLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);

    while(GetIsObjectValid(oTarget))
    {
		SendMessageToPC(GetFirstPC(),"oTarget is valid.");
        float fDelay = GetDistanceBetweenLocations(lLoc, GetLocation(oTarget))/20;

        if(!GetIsReactionTypeFriendly(oTarget))
        {
		   SendMessageToPC(GetFirstPC(),"oTarget is not friendly.");
            if (MyResistSpell(OBJECT_SELF, oTarget, fDelay) <= 0)
            {
            int nReflexCheckHack = GetReflexAdjustedDamage(2, oTarget, nDC, SAVING_THROW_TYPE_FIRE, OBJECT_SELF);
			SendMessageToPC(GetFirstPC(),"GetReflexAdjustedDamage cheked.");
                switch (nReflexCheckHack)
                {
                    case 0: // Evasion/Improved Evasion, or equivalent modifier
                        // Nothing here, resisted all effects
						SendMessageToPC(GetFirstPC(),"Target resísted all effects.");
                    break;

                    case 1: // Reflex save: Success
						SendMessageToPC(GetFirstPC(),"Reflex save success.");
                        nDamage = nDamage /2;
                        eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
                        eVis = EffectVisualEffect(VFX_IMP_FLAME_S);

                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
                    break;

                    case 2: // Reflex save: Failure
						SendMessageToPC(GetFirstPC(),"Reflex save failure.");
                        eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
                        eStun = EffectStunned();
                        eVis = EffectVisualEffect(VFX_IMP_FLAME_M);

                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStun, oTarget, 1.0));
                        DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
                    break;
                }
            }
        }
    oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, RADIUS_SIZE_LARGE, lLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
    }
}

void main()
{

	SendMessageToPC(GetFirstPC(),"Eruption script is running");

    location lLoc = GetSpellTargetLocation();

    EruptionGroundVFX(lLoc);
    DelayCommand(2.0, Eruption(lLoc, d6(12), GetSpellSaveDC()));
    DelayCommand(4.0, Eruption(lLoc, d6(6), GetSpellSaveDC()-2));
    DelayCommand(6.0, Eruption(lLoc, d6(3), GetSpellSaveDC()-4));
}

The advantage of using @tinygiant 's way of doing the SendMessageToPC thing is that you can just put the int DEBUG_ME to FALSE and then leave the script as it is. With my method you have to erase all the SendMessageToPC after you’ve checked and everything works. For me this is no big deal since I know how to do that, but maybe you’ll find it easier to use tinygiant’s method. If that’s the case I can modify this script to his system.

1 Like

I tested his debug script (which compiled). But it did not show anything.

I will try your script now.

Yeah, no surprises there. You only declared what his function does but probably didn’t use it in the void main() after.

Ok tested it. Your script worked the first time I cast the spell but not the second or third time. See image below.

Strange it killed a rat - but I saw no damage numbers on the rat. But none of the undead were damaged. Tell me what is going on with this script.

To me it seems it worked the first two times, but there was a Reflex save success…

And according to the messages it seems the undead are not valid objects for some reason. Otherwise the “oTarget is valid would have appeared” in the chat. I mean, you can see with the messages that the script is running when you fight the undead.

Nope I cast it three times. Only the first time your debugging script ran all the way. The other two times it just said: “Eruption script running” and it did not give full details as the first time.

And why isn’t the spell doing damage to the undead I cast it on?

I have no idea. You tell me. I don’t know how these spells work in NWN.

Yeah…the spell is not working at all…just that one time. Same for your debugging. It only worked that one time. The very first time I cast the spell. Weird.

The debugging worked the other times too. You get the message “Eruption script running” three times, didn’t you? I can see that in your picture.

I mean, the only thing I can deduce from the script is that when you fire the spell at the undead, for some reason the target is not a valid object:

while(GetIsObjectValid(oTarget))

The script doesn’t go past this point when you fire at the undead. Otherwise you would have seen other messages.

BUT…your script only shows the full description on the very first casting…not on the other castings. It just say the script is running but not the breakdown like on the first casting.

Precisely. Just like I said in my post above:

EDIT: while(GetIsObjectValid(oTarget)) could be translated as: If the target is a valid object the next part of the code will run.

EDIT2: If you look at the code, you see that’s where the other messages are. Can’t you see that?

I’m talking about this part below:

eruptioni spell test2

Where they don’t do the full decription as the first part on first casting.

eruptioni spell test3

We’re talking in circles here. I can only point to what I have already said.

I guess after I cast the spell the second and third time I was expecting the breakdown…

oTarget is valid
oTarget is not friendly…etc

But those descriptions never showed up on the second and third castings…

I know:

For some reason the game doesn’t seem to think the undead is a valid object/target. WHY that is, I have no idea. But we can draw those conclusions from the messages you get ingame from the script. The script is still running. It just doesn’t get past the while(GetIsObjectValid(oTarget)) and the code you have there, where all the damage and whatnot is done.

1 Like