Need help with this script (RESOLVED)

Accordind to this discussion

OnMeleeAttacked should work on pcs. So replace EVENT_SCRIPT_CREATURE_ON_DAMAGED with EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED and see if that works better.

EVENT_SCRIPT_CREATURE_ON_DAMAGED definitely works for PCs.

What does not seem to work is linking the VFXs. And this seems to make the whole spell effect invalid and it is not applied to the caster. So when the caster is hit the OnDamaged script fires but since GetHasSpellEffect() returns FALSE no damage is applied to the attacker.

Removing all but one VFX (or applying the VFXs separately) fixes this.

See lexicon for this: EffectLinkEffects(effect, effect) - NWN Lexicon

So linking a non visual (dummy) effect is probably the best solution.

Here are the slightly modified scripts:

// sp_prismsph
// Prismatic Sphere



#include "nw_i0_spells"
#include "x2_inc_spellhook"

void ApplySphereEffect(object oPC, int nSPELL, int nSTACK)
{
    // Apply visual effects to represent the sphere (Ion Stones and Globe of Invulnerability)
    float fDUR = 60.0 * GetCasterLevel(oPC);
    effect eFX = EffectVisualEffect(VFX_DUR_GLOBE_INVULNERABILITY);
    eFX = EffectLinkEffects(eFX, EffectVisualEffect(VFX_DUR_IOUNSTONE_BLUE));
    eFX = EffectLinkEffects(eFX, EffectVisualEffect(VFX_DUR_IOUNSTONE_GREEN));
    eFX = EffectLinkEffects(eFX, EffectVisualEffect(VFX_DUR_IOUNSTONE_RED));
    eFX = EffectLinkEffects(eFX, EffectVisualEffect(VFX_DUR_IOUNSTONE_YELLOW));
    eFX = EffectLinkEffects(eFX, EffectSpellImmunity(nSPELL));
    eFX = SetEffectSpellId(eFX, nSPELL);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFX, oPC, fDUR);

    //Set the script handlers if not cast already to avoid loss of the original script
    if (nSTACK) return;
    string sSCRIPT = GetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_DAMAGED);
    SetLocalString(oPC, "ORG_DMG_SCRIPT", sSCRIPT);
    SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "dmg_prism_custom");
}

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

    object oPC = OBJECT_SELF;

    int nSTACK = FALSE;
    int nSPELL = GetSpellId();
    int nStrRef = StringToInt(Get2DAString("spells", "Name", nSPELL));
    SetLocalInt(oPC, "PRISM_SPHERE_ID", nSPELL+1);

    if (GetHasSpellEffect(nSPELL, oPC))
    {
        nSTACK = TRUE;
        RemoveSpellEffects(nSPELL, oPC, oPC);
    }

    DelayCommand(0.01,ApplySphereEffect(oPC, nSPELL, nSTACK));
}

and


// dmg_prism_custom
#include "nw_i0_spells"

void main()
{
    // Does not trigger against allies that accidentally hit you
    object oPC = OBJECT_SELF;
    object oAttacker = GetLastDamager(oPC);
    if (!GetIsEnemy(oAttacker, oPC)) return;

    // Reset the script handler & and do some cleanup
    int nSPELL = GetLocalInt(oPC, "PRISM_SPHERE_ID") - 1;
    DeleteLocalInt(oPC, "PRISM_SPHERE_ID");

    string sSCRIPT = GetLocalString(oPC, "ORG_DMG_SCRIPT");
    SetEventScript(oPC, EVENT_SCRIPT_CREATURE_ON_DAMAGED, sSCRIPT);
    DeleteLocalString(oPC, "ORG_DMG_SCRIPT"); 

    if ((nSPELL==-1) || !GetHasSpellEffect(nSPELL, oPC)) return;

    // Effect 1: Blind creatures under 8 HD
    if (GetHitDice(oAttacker) < 8)
    {
        if (!MySavingThrow(SAVING_THROW_FORT, oAttacker, 20, SAVING_THROW_TYPE_SPELL, oPC))
        {
            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBlindness(), oAttacker, RoundsToSeconds(10));
        }
    }

    // Effect 2: Take 1d10 of all damage types
    if (!MySavingThrow(SAVING_THROW_FORT, oAttacker, 20, SAVING_THROW_TYPE_SPELL, oPC))
    {
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_ACID), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_FIRE), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_BLUDGEONING), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_PIERCING), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_SLASHING), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_COLD), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_ELECTRICAL), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_DIVINE), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_NEGATIVE), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_POSITIVE), oAttacker);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_SONIC), oAttacker);
    }

    // Effect 3: Will save or die
    if (!MySavingThrow(SAVING_THROW_WILL, oAttacker, 20, SAVING_THROW_TYPE_DEATH, oPC))
    {
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oAttacker);
    }

    // Effect 4: Fortitude save or be poisoned (Wyvern Poison)
    if (!MySavingThrow(SAVING_THROW_FORT, oAttacker, 20, SAVING_THROW_TYPE_POISON, oPC))
    {
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectPoison(POISON_WYVERN_POISON), oAttacker);
    }

    // Effect 5: Will save or be confused for 2d10 rounds
    if (!MySavingThrow(SAVING_THROW_WILL, oAttacker, 20, SAVING_THROW_TYPE_MIND_SPELLS, oPC))
    {
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectConfused(), oAttacker, RoundsToSeconds(Random(19) + 2));
    }

    // Effect 6: Reflex save or be petrified
    if (!MySavingThrow(SAVING_THROW_REFLEX, oAttacker, 20, SAVING_THROW_TYPE_SPELL, oPC))
    {
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectPetrify(), oAttacker);
    }

    //The sphere dissipates. Remove effect and reset the script handler
    RemoveSpellEffects(nSPELL, oPC, oPC);
}

I’ve used EffectSpellImmunity(nSPELL) as ‘dummy’ effect but perhaps there’s a better solution.

With the original OnDamaged script I was able to kill both attackers. To (hopefully) prevent this I added a DeleteLocalInt(oPC, "PRISM_SPHERE_ID"); and I also store nSPELL+1 (instead of just nSPELL) so I can validate the value of GetLocalInt(oPC, "PRISM_SPHERE_ID") -1 (has to be >= 0 and will be -1 (and not just 0) if the spell isn’t active anymore but for some reason the OnDamaged script is still set).

There are still some things to improve: for example it should be checked if the damager actually is a creature. Currently the spell also works on trapped placeables.

2 Likes

Great work, @Kamiryn ! I’m sure @Imtherealthing will be pleased!

I did not do much. Most credit goes to @Clangeddin

@Kamiryn - That’s fair. @Clangeddin did the heavy lifting, I suppose, but you still refined the thing to make it actually work all the way in the end. That’s a thing that I wasn’t capable of, so you still deserve credit.

I did not test the scripts myself as I didn’t have the time yesterday, but I thought they would work because I found this page:

which states:

So I thought it would work, but I’m glad you managed to make it work in the end, I suppose the problem was that the link effects was not properly working with the visual effects and therefore it was not properly applying the spell to the character, therefore the ondamaged event would return as it would not find the spell on the PC.

2 Likes

If you were dealing with this in nwn2 (I don’t remember if seteventscript type thing exists), I’d probably go temp cast spell property on armor/skin there too. (Effectsharedamage might work, but that’s even hackier/uglier.)

Think clangeddin did pretty good, just wouldn’t want to lose a script handle that works so something like…which is why I’d use an item prop.

// Check the module scripts for nui, gui, target.
// Update and save the previous script name as local, exectute that on those handles
void replaceModuleScripts()
{
    string sScript = GetEventScript(GetModule(), EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT);
    if(sScript != "mod_gui_event") {
        SetEventScript(GetModule(), EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT, "mod_gui_event");
        SetLocalString(GetModule(), "PREV_MODULE_GUI_SCRIPT", sScript);
    }
    // execute original script on this event, hopefully it doesn't eat all our instructions
    string sScript = GetLocalString(GetModule(), "PREV_MODULE_GUI_SCRIPT");
    if(sScript != "") {
        ExecuteScript(sScript);
    }
    // additional script to change script when spell expires

(nwn2 has Get/SetEventHandler functs)

Hi andgalf…I appreciate your effort. I never really know how these scripts can end up being so complicated. I’m an ideas guy…not a scripter…I ask whomever can do it to help me. Sorry about not putting the scrolls on the ground. I put them in a chest because I thought the scrolls would look better in a chest than scattered all over the ground. :slight_smile:

HOLY CAMOLE!!..SO MANY REPLIES.

THANKS EVERYONE!!

I tested the final scripts and all of you did a great job. Thanks. The spell works as it should. The vfx is good. Only one thing (if it is possible) would be to tell the PC which of the effects killed the creature who attacked it. To have in the chat bar say…“the creature was killed by or effected by…”

But if that isn’t possible…I love it as it is.

All of you get credit on this when I get a chance to upload it to the vault. It is Friggin awesome!!

1 Like

Hopefully you NWN 2 guys can create this spell for your game version. :slight_smile:

THANKS ALL. i’M RELEASING THIS TO THE VAULT AND YOU ALL GET CREDIT.

2 Likes

Nah, I think I’ll keep going with the simpler stuff. :slight_smile:
Like, making a closed door talk to you under certain conditions, spawning placeables when the PC does something, trigger a conversation when using or “activating” a book, or opening an “input box” where you can write your answer to a riddle and then checking inside a conversation if your answer was correct. Stuff like that are pretty easy in NWN2 once you’ve done it a few times in a couple of modules. That’s more up my alley. :yum:
And I’ll keep concentrating more on characters, dialogue and story since that’s what interest me the most when making a campaign/module. And making the companions look good, of course. :wink:

Anyway, I’m glad it got sorted out for you!

:slight_smile: hanks andgalf bud…:slight_smile: