NEW Special abilities / Spells for NPCs

Our players do not get NPC companions beyond like the animals and familiars used by casters and rangers/druids. Is the Henchspells actually a relevant concern for us then? Our AI is custom made so we do not use Stock scripts. I hate to have to have a specialized script written for every creature that uses special abilities.
I am reading about HenchRacial and HenchClasses2da’s . .where does one even find these? I have looked through the original game files and not seeing them

it depends on whether their ai-scripts call HenchDetermineCombatRound().

And it’s relevant only to creatures that actually have your custom spells/feats. Any creatures that don’t have those new spells/feats can get by with the stock HenchSpells 2da

There are many ways to start fights, slot ai-scripts, etc.

After poking around a bit I really shouldn’t make generalizations about the AI, such as when DetermineCombatRound() or HenchDetermineCombatRound() gets invoked.

Because I just noticed that the nw_c2_default* scriptset (the MotB and SoZ versions but not the OC version) calls HenchDetermineCombatRound() … like the gb_comp_* and gb_assoc_* scriptsets.

(and I no longer assume that the AnimalCompanion and Familar associates have the gb_assoc_* scriptset … from what I see they don’t )

the long & short is, HenchDetermineCombatRound() uses HenchSpells.2da (and if applicable HenchClasses/HenchRacial 2das) but DetermineCombatRound() doesn’t,

so, uh, have you got the spells/feats showing in the toolset yet?


it looks like they’re exclusive to Tony’s AI 2.2, i also see only HenchSpells among the stock 2das …

Sorta . . . I can access the newer spells by tossing the Spells2da in the Override at least . . … for the life of me I cannot get my Gorgon to use its Breath, Petrification ability though

is it a Feat ? if so, look it up in Feat.2da

from there, look up its “SPELLID” in Spells.2da …

Ironically, i see in Spells.2da #495 “Breath_Petrify” and it clearly looks like a spellability, which ought to have a feat associated with it, but when i look in Feat.2da I can’t find anything related.

so you might be dealing with some of Nwn2’s unfinished business … it might have to be “wired up” before it works

(and yes it might pertain to henchspells)

OH unfinished . .Yay. . . . I didn’t think the original game set had any creature with petrifying breath in it yet the option clearly Looks like it from the originals. It would certainly explain the issue with it just wanting to gore people and not use a breath weapon . . . Shame though . . … sweet models but can’t set them up per SRD

here’s a thread that @Lance_Botelle and i dickered about with… Iron Golem w/ poison attack

note things can get working but you sorta have to do that on your own for your unique setup. You could, for example, try to set the Gorgon up with another attack, getting one that works perhaps, then mimic that setup for the petrification ability …

1 Like

Wading through the henchspells I found that the Breath Petrify is currently set to Attack instead of DragonBreath like all the other Breath weapons I have looked at so far. I think I will try changing that up and moving the weight up just a tad to see if it will do its breath attacks


here’s what my Iron Golem looks like …



I use TlkEdit2 to find the strref for “Iron Golem Poison Gas”


then reference that back into Spells.2da “Name” column to find the special ability


and check its “UserType”

Then look at the HenchSpells entry that corresponds to spellid #263

(no Feat req’d it looks like)

as a test I just changed the golem’s SpecialAbility to #495 “Breath, Petrification” and it worked fine here. EffectWeight was already set to “1.0” and spelltype is “attack” …


Is there a specific reason for the Iron Golem Poison gas being listed in the TLK ? I know that it is not on ours [just checked], How would you know if a Feat was required?

I don’t understand why my Gorgon will not use the breath weapon then . . something in our custom scripting perhaps

it’s in the backup of the original Dialog.Tlk i kept … #5294 … so i dunno

when looking at a Spells.2da row, there are several indicators. It may have only an Innate level, but no levels listed under Bard,Cleric,Druid,etc. however there are spellrows that multitask by serving as both spell(s) and feat(s). So that’s not an absolute def’n. Most importantly check the UserType column: 1=spell, 2=specialability, 3=feat, 4=itemcast. But that can be ambiguous if, again, a spellrow was multitasked as noted. Third, look at the FeatID column; that’s a reference to a Feat.2da row (if it exists). And Feat.2da contains a reference back to Spells.2da under its SPELLID column. Unfortunately only one of those refs is necessary … either Feat->Spell or Spell->Feat i forget which though. So sometimes it’s been left out or is just plain wrong …

Also, sometimes it’s a good idea to search for an ImpactScript (aka. spellscript) string throughout Spells.2da – the same script might be used on multiple spellrows, just to keep things confusing.


this is where you have to start looking for what core-AI it’s using. My golem is using the nw_c2_default* scripts … so when my PC walks up to it, one of several events could fire-up combat:

nw_c2_default1 - OnHeartbeat          - can fire HenchDetermineCombatRound() or HenchDetermineSpecialBehavior()
nw_c2_default2 - OnPerception         - ditto
nw_c2_default3 - OnEndCombatRound     - ditto
nw_c2_default4 - OnConversation       - can fire HenchMonRespondToShout()
nw_c2_default5 - OnPhysicallyAttacked - can fire HenchDetermineCombatRound() or HenchDetermineSpecialBehavior()
nw_c2_default6 - OnDamaged            - ditto
nw_c2_default8 - OnDisturbed          - can fire HenchDetermineCombatRound()
nw_c2_defaultb - OnSpellCastAt        - can fire HenchDetermineCombatRound() or HenchDetermineSpecialBehavior()

Any of those functions goes into what I call the SoZ ai. ( The SoZ ai uses HenchSpells.2da )

it just occurred to me that, if the Gorgon’s scripts call either DetermineCombatRound() or HenchDetermineCombatRound() … an X2_SPECIAL_COMBAT_AI_SCRIPT script can be set up to (force)run its petrification.

But, as you suggest, the custom ai scripting is what fundamentally needs to be looked into

Seems my iron Golem doesn’t use its breath weapon either

Looked through our versions of all the scripts, which are hooked into our custom stuff, you indicated and they do all use the Henchxxxxxxxxxxxxx coding .

if i were you I’d create a new, standalone module with a plain outdoor area and place a creature in it. Clear the creature’s scriptslots. Give it the special ability “Breath, Petrification” with a few uses. Then write a small script like this, that can be assigned to any (but in practice only one) of its scriptslots:

#include "nw_i0_generic"
#include "hench_i0_ai"

void main()
    SendMessageToPC(GetFirstPC(FALSE), "RUN [event_type]");

    // uncomment only ONE Of these:
//    DetermineCombatRound(); // nw_i0_generic
    HenchDetermineCombatRound(); // hench_i0_ai

Perhaps the OnPhysicallyAttacked event. Then load the module and take a swing at it … see what happens.

Try it first with a clean /override folder, then try it again with TonyK’s AI 2.2 in your /override

I’d also copy and compile the #495 ‘x0_s1_petrbreath’ script into the module folder. The stock script looks like this

//:: Petrification breath monster ability. 
//:: Fortitude save (DC 17) or be turned to stone permanently.
//:: This will be changed to a temporary effect.
//:: Copyright (c) 2002 Floodgate Entertainment
//:: Created By: Naomi Novik
//:: Created On: 11/14/2002

#include "x0_i0_spells"

void main()
    SendMessageToPC(GetFirstPC(FALSE), "x0_s1_petrbreath"); // kL_add.

    object oTarget = GetSpellTargetObject();
    int nHitDice = GetHitDice(OBJECT_SELF);

    location lTargetLocation = GetSpellTargetLocation();

    //Get first target in spell area
    oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, 11.0, lTargetLocation, TRUE);
        float fDelay = GetDistanceBetween(OBJECT_SELF, oTarget)/20;
        int nSpellID = GetSpellId();
        object oSelf = OBJECT_SELF;
        DelayCommand(fDelay,  DoPetrification(nHitDice, oSelf, oTarget, nSpellID, 17));

        //Get next target in spell area
        oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, 11.0, lTargetLocation, TRUE);


Or you can use my re-script that looks like this

// 'x0_s1_petrbreath'
    Petrification breath monster ability.
    SpellID 495 - special ability

    Fortitude save (DC 17) or be turned to stone permanently.
    This will be changed to a temporary effect.

    Copyright (c) 2002 Floodgate Entertainment
// Created By: Naomi Novik
// Created On: 11/14/2002

#include "x0_i0_spells"

void main()
    SendMessageToPC(GetFirstPC(FALSE), "x0_s1_petrbreath"); // kL_add.

    object oCaster = OBJECT_SELF;

    int iDuration = GetHitDice(oCaster);
    int iSpellId  = GetSpellId();

    location lSpell = GetSpellTargetLocation();
    object oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, 11.f, lSpell, TRUE);
    while (GetIsObjectValid(oTarget))
        float fDelay = GetDistanceToObject(oTarget) / 20;
        DelayCommand(fDelay, DoPetrification(iDuration, oCaster, oTarget, iSpellId, 17));

        oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, 11.f, lSpell, TRUE);

The SendMessageToPC() will notify you in the chatbox if/when the specialability executes. Unfortunately there are many reasons why it might not …

heh I was just looking that up and have found it missing from our scripts in general. I am going to test it with our Custom Spells include script and see if that solves my issue.

Question-- I see its using spell ID 17 where is that # from since the petrify is like 495 on the Spells2da? Or is that just the DC of the spell to beat?

that’s the FortSaveDC

use this to print the SpellID

SendMessageToPC(GetFirstPC(FALSE), "spellId= " + IntToString(GetSpellId()));

Tried with the script in the mod . . . . original / with our spells_i , and KevL_s option above . . . nothing I do works to get it to use its
breath . . . tested our iron Golem as well . It also does not use its breath weapon.

then it sounds like you or someone comfortable with debugging – script editing and recompiling – should trace the AI. For the following screenshots i had to increase the EffectWeight of breath-petrification in HenchSpells.2da from 1.0 to 10.0 because my dwarf is pretty tuff … the golem wouldn’t cast against my PC at a weight of 1.0 … ( 10.0 is too high for regular play though, I just wanted to ensure that the golem would use the specialability – tbh 2.0 would probly be sufficient against an L16 Cleric )

as you can see, this sort of debugging is kinda advanced …

Our Iron golem currently has a Effect Weight of 0.1 . . might be part of the issue. Will Monsters work the same against NPCs as they do against PCs? At this point have only been testing them
against other NPCs. Also… did I read somewhere that the henchspells2da should not have any blank lines to it? Or was that my imagination?

yeh try just womping it up to 10.0 and back it off later

in my experience yes. In my testrun above the golem breathed on me ( a PC ) and there was a neutral bandit ( npc ) behind me that got caught in the AoE – so it went hostile on the golem …

the golem then breathed again and petrified the bandit also …

depends what you mean by blank line. RowIds should be consecutive and all fields should have a legitimate value or at least be “****”

but there doesn’t have to be spells on every row. They just have to be in synch w/ Spells.2da. For example here’s an arbitrary screenshot of my HenchSpells showing a couple of blank lines

(those entries are down among Kaedrin’s PrC additions)