How do I create a persistent poisonous cloud?

The idea is for a “poisonous cave” – a cave full of a poisonous gas that acts like a permanent stinking cloud except that it is a poison rather than spell and thus is affected by Iron Guts and Neutralize Poison (antidote potions). Fort save vs. poison; failure is the Dazed effect (just like stinking cloud).

So I was thinking that this could be accomplished by using an Area Heartbeat script requiring a Fort save vs. Poison (DC 16) but I’m at a loss as to how to script that.

Any ideas? Thanks in advance!

Maybe create an Area of Effect whose heartbeat applies a poison effect on Fortitude Save failure.

Should this be a ticking thing, where the dazed effect is applied for a few seconds and after that, they get another fortitude save chance to avoid the next few seconds of dazedness? If they drink an antidote potion prior to entering the area, should they be immune to the effects entirely? If they drink an antidote potion while in the area, should they stop being affected permanently, or temporarily? Are they supposed to be taking damage while in there as well? Is the effect supposed to exist throughout the entire area, or are there supposed to be breathable-space safezones in it? Are only PCs supposed to be affected, or should it hit associates as well? What about enemy creatures?

Checking up on it, the neutralize poison spell effect seems to just cycle through the effects on the target and remove any EFFECT_TYPE_POISON ones it finds. :thinking: Drinking or casting Neutralize Poison within the area wouldn’t make a difference unless the Dazed effect is linked to a permanent Poison effect that gets applied once on area enter and stays gone thereafter.

I think I’d go with modifying the neutralize poison spell script to set a timestamp for when the player last drank an antidote, and start a pseudoheartbeat in the area that runs only while players are inside it, and cycle through the living creatures in the area (relative to a hidden poison source object), checking for the antidote timestamp to see whether they’re supposed to be immune to the poison. If they’re not immunized, do the fortitude save, temporarily apply Dazed.

Safezones could be designated via triggers, setting and removing a local int on entering objects, by excluding creatures that have that integer set on them.

That’s exactly how you can do that. Iterate over every living creature in area, do fort save on them:

if(FortitudeSave(oCreature, 16, SAVING_THROW_TYPE_POISON) == 0)
    /* apply nasty effects here */

The saving throw call takes poison immunity into account, so no extra code is needed. You need however check for doubled effects, i.e. so you don’t add the Dazed twice.

1 Like

before i suggest anything, two questions:singleplayer or multiplayer? do you use or intent to support cpp features?

Enhanced Edition, Single Player, no CPP (at this time; possibly in the future).

well if it is singleplayer then heartbeat is no issue and easiest way to do it, as for script itself

here is slighly modified stinking cloud spell script from cpp that should work as is in area heartbeat:

void main(){

effect eStink = EffectDazed();
effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
effect eLink = EffectLinkEffects(eMind, eStink);
eLink = EffectLinkEffects(eLink, eDur);
eLink = ExtraordinaryEffect(eLink);

effect eVis = EffectVisualEffect(VFX_IMP_DAZED_S);
effect eFind;
float fDelay;
//Get the first object in the persistant area
object oTarget = GetFirstPC();
    if(GetArea(oTarget) == OBJECT_SELF)
        fDelay = GetRandomDelay(0.75, 1.75);
             //Make a Fort Save
            if(!MySavingThrow(SAVING_THROW_FORTITUDE, oTarget, 666, SAVING_THROW_TYPE_POISON, OBJECT_INVALID, fDelay))
               //Apply the VFX impact and linked effects
               if(!GetIsImmune(oTarget, IMMUNITY_TYPE_POISON))
                   DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(2)));
                   //engine workaround to get proper immunity feedback
                   ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectPoison(POISON_ETTERCAP_VENOM), oTarget);
                //If the Fort save was successful remove the Dazed effect
                eFind = GetFirstEffect(oTarget);
                    if(GetEffectCreator(eFind) == OBJECT_SELF)
                        RemoveEffect(oTarget, eFind);
                    eFind = GetNextEffect(oTarget);
    //Get next target in spell area
    oTarget = GetNextPC();

now CCP could allow to make this poison cure-able via potion but that would be bit more complicated (unless you are fine setting area tag to “70_EC_POISON”) and you would have to include the neutralize poison spell script in module or otherwise it would work only for players that uses CCP

1 Like

So I successfully created the heartbeat script. And boy does it suck to be a PC! Having to save versus poison every round is a real PiTA if the entire cave is filled with a (pseudo) stinking cloud. The poison-immune monster just devours the PC and his retainers. The only hope for the PC and his team is to apply a true poison effect so that they can drink antidote potions (and/or cast neutralize poison), rather than a pseudo-poison effect.

Based on how effects work, it appears that I have to use an existing poison or create a new one (couple of scripts and a new poisons.2da row). There are only two existing poisons that do not do damage. Carrion Crawler Brain Juice will instantly paralyze you if you fail your DC 13 fort saving throw. Potion of Iron Guts gives a +4 so that gives a 6th level wizard of save of 7. However if you fail your save, you can’t drink a neutralize poison while paralyzed. Oil of Taggit is the other alternative but that has a DC of 15 with an initial effect of nothing and a secondary effect of sleep. One the one hand if you notice your saving throw failure, you can try and immediately drink that antidote, otherwise sleep = death!

So, I’m leaning towards creating a custom poison with an initial effect of Daze since you can still drink potions while dazed. As a single-player module, it’s risky to assume that the PC will have a retainer who can and will cast remove poison before they themselves are poisoned (or is a 9th level druid & immune).

And I think creating a custom poison is the better way to go rather than using a spell-hook to catch neutralize poison or modify neutralize poison directly, as it follows BioWare’s design intention.

Thanks for everyone’s help so far! I’ll update once I create the custom poison and test the encounter.

@TheBarbarian - there are no pockets of air by design. The entire cave is filled with the foul breath (Italian mala aria) of the monster lurking inside.

creating new poison or using poison itself is pointless here

without using CPP poison system or your own rewrite, neutralize poison won’t be able to cure the daze effect. Neutralize poison spell (the antidote potion) only removes the poison effect itself or ability decrease effect, if some poison has another effects they are ignored (which is what CPP fixes).

If you use the script I posted above you get basically the same effect as if you created new poison, except there won’t be the poison icon. (which is in my opinion actually a good thing so already poisoned player from other sorce won’t be immune to this cave).

1 Like

I’d avoid making new poison effects just for one cave.

Four ideas:

  1. Lower DC to 5 or 10. With a roll every round you have almost a guarantee NWN’s PRNG will return a nice 1 for you.
  2. Make the Daze effect last only one round. This will lower the change of getting everyone in the party disabled at the same time.
  3. Spawn mask items somewhere which add some bonuses versus poison. This item property is cheap, so there is little monetary gain for selling them.
  4. Instead of “poison gas”, think of “choking gas” - look below.

How about instead of Daze you use another effect like Blindness or Slow? Or old plain negative attack bonus coefficient + increased spell failure. This way the party can tough it out without having to chug down tons of antidote potions.

Final idea: modify the Neutralize Potion script (NW_S0_RemEffect) to grant the target limited poison resistance / immunity.

@Shadooow - I like your idea of removing the daze effect with a successful saving throw. I had to fix three typos but otherwise the script works as advertised.

@NWShacker - Good ideas also.

Both of you have given me some good food for thought.

I’m also considering changing the neutralize poison spell because the D&D 3.5 version of the spell grants poison immunity for 10 mins/level of caster (not in the 3.0 version which NWN uses). The drawback of changing the neutralize poison spell is that it completely changes the challenge of the encounter. So long as the player drinks his antidote potion and gives one to each of his associates, then the encounter is significantly weakened. I don’t mind having a druid cast neutralize poison since this is a module for 5th level characters, so perhaps the real issue is access to antidote potions. . …

I just might also have to reconsider @TheBarbarian 's idea of air pockets.

This definitely requires some deep thinking. Thank you everyone for your contribution!

Another thought for the bucket: The timestamp route could factor in the amount of time passed since the last time someone drank an antidote/cast a neutralize spell, reducing the effect of the antidote/spell tick by tick until it wanes away into nothing, making the player have to drink more than one potion/cast more than one spell over the course of the encounter.