Creating a Henchmen Level by Level

Hello everybody

I created a Dwarf fighter henchmen and chose the “default fighter” class package. Turns out it specializes in longswords, and my henchmen is a burly dwarf. Dwarfs with longswords are just… wrong. So I would like for him to specialize in warhammers.

I searched online and read that you could make a custom package editing the package.2da. I coulnd’t find it in the game files so I downloaded one here from the vault. But I don’t know to change anything, it’s all moon language.

Once I read that you could make a henchmen version of itself for each level up, defining equipment and feats. Could that be the solution for my case? Could I do that and save it in an .erf file and never do again?

Another thing: How can I make the henchmen use feats like called shot, disarm and expertise?

Thank you very much and have a great day.

1 Like

Making a new template for each level is obsolete. Much easier to define the package. Then use LevelUpHenchman in a script.

Perhaps someone else knows of a tutorial for packages?

Here’s an explanation of 2da files and packages to get you started.

You need to change a few 2da files, using info from several others, but don’t be put off - the only skill you need is editing lists in text files.

To obtain the official 2da files, use NWNExplorer to open data\base_2da.bif (assuming you have the latest release of EE).

2 Likes

Looking at the info you sent I kind of understand how the packages.2da works, but some options are still unknown to me, like how to set feat and skills. Let’s hope someone point out a tutorial

Thank you very much.

Taking feats as an example, clearly you need to create a PackFT*.2da file. Looking at examples should give you a clue to how feats are linked to levels. The actual feat numbers are defined in feats.2da but you won’t need to change that. Spells and skills similarly.

It’s a while since I did this, but it’s not too difficult if you have a go.

1 Like

I see. How could I obtain an example of PackFT*.2da and the skills one for me to see? I quickly seached the vault and couldn’t find any.

Thank you.

Using NWNExplorer as mentioned above. For example, PackFTBarb1.2da is a feat package for Barbarian. It is simply a list of feats in descending priority order, with a label describing the feat number for legibility (the label does nothing in game).

The creature levelling up will receive the highest priority feats to which they are entitled under the rules in feat.2da. For example, they will not receive epic feats until they achieve epic levels.

It isn’t normally necessary to change the rules in feat.2da. Just take an existing package as a starting point, then tweak the priority order, omitting any unwanted feats.

I understand. It is located in base_2da.bif, right? Is there an easier to find it? All the values are res***…2da, and there are more than 500. I’m supposed to look at one by one and recognize by eye? Because nowhere is written, for example, PackFTFight1.2da.

Thank you very much.

Did you enter the path to your EE installation in NWNExplorer’s Settings?

If that doesn’t work, in NWNExplorer, use the big Open button. Navigate to the EE game installation data subfolder, then open nwn_base.key.

The game files will now be legible.

1 Like

Hello!

I see my mistake. I entered the path but I was using the open button and using the file that I copied to my desktop. Now I navigate through the game files and everything is fine.

I managed to edit the feat, skill and packages 2das, and got it working! The only thing that is pending is that in the packages.2da the name and description is a sequence of four numbers, how do I edit that? In the toolset, for the henchmen creation I can see the label I created, but in the game it gets bad sitref. It is not important as it is working, it’s just finishing touches.

Thank you very much, I couldn’t have done without your help.

The strref fields are line numbers in the .tlk file, which is just a list of strings.

A module can only have one custom .tlk file in its Module Properties > Custom Content.

If you don’t already have one (for CEP or whatever) you can make a small one with one of the tlk editors on the Vault.

Maybe someone can recommend a good one (preferably one that automatically adds the offset - readers will know what I mean by that).

I see. In this case it isn’t really necessary, I just need for the henchmen and I can identify by the label in the toolset. Thank you.

If I may abuse your goodwill, once I did something, I don’t know if was henchmen scripts I chose, or it was something in the module I was playing, but when the henchmen died, it would fall on the floor on near death, wouldn’t be expelled from the party, and would only get up if healed by a spell, healing kit or potion. It wouldn’t die. Do you know what it was?

Thank you very much.

That’s probably what that henchman system is designed to do. I remember playing modules like that.

If that’s not for you, maybe easiest to find a system that does what you want.

The behaviour you’re seeing might well be based on the SetIsDestroyable setting, or SetImmortal, with extra code to manage revival.

It’s a tricky area to tinker with. You have to tweak SetIsDestroyable before death occurs, RemoveHenchman etc on death.

Whatever you do, few players actually want their companions to die permanently!

Sorry, I think I wasn’t clear. I build these henchmen to put on other people’s module to emulate a party and play for myself. My henchmen use the HoU script for death, that means when they die the only solution is Raise Dead or loading game. It is a little frustrating for example for a thief that rushes and dies easily, and I’m not able to configure Balkoth’s Minion Companion to control them.

So what I want is exactly this that I saw in the module once. Actually the module was “The Sinister Secret of Saltmarsh”. I redownloaded and I am fiddling with it but I can’t discover. I think is super useful for the henchmen to lay on the floor near death waiting for healing, as you have little control over them.

I don’t know if it was something in the module or some henchmen script that I changed. It must be something done already because my knowledge of the Toolset was lesser back than, and it is minimal now.

Thank you very much.

Put this script as your henchman’s OnDeath to make it stay in the party while dead and raise automatically when there is no enemy nearby.

OnDeath
void raise()
{
    // break the loop if became alive outside this script
    if(!GetIsDead(OBJECT_SELF))
    {
        return;
    }

    // find nearest alive enemy creature
    object oEnemy = GetNearestCreature(
        CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, 1,
        CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);

    // stay dead if seen by this enemy, otherwise - raise
    if(GetObjectSeen(OBJECT_SELF, oEnemy))
    {
        FloatingTextStringOnCreature("Seen by an enemy (" +
            GetName(oEnemy) + ") - staying dead", OBJECT_SELF);
        DelayCommand(6.0, raise());
    }
    else
    {
        ApplyEffectToObject(DURATION_TYPE_INSTANT,
            EffectResurrection(), OBJECT_SELF);
    }
}

void main()
{
    // remember current master
    object oMaster = GetMaster();
    // set self as undestroyable, raisable and clickable
    SetIsDestroyable(FALSE, TRUE, TRUE);
    // re-join master after kicked from party due to death
    DelayCommand(0.0, AddHenchman(oMaster));
    // begin auto-raise loop with 6-second interval
    DelayCommand(6.0, raise());
}
Fun stuff

If you serve the corpse a potion, it will actually drink it (with animation and VFX), essentially wasting it, unless you use spellhook to make a better use of it:

EDIT: fixed the script to respond to external resurrection.

2 Likes

This script is amazing, Thank you very much!

I made a quick fix to that script to prevent the resurrection loop from running when the NPC is resurrected by other means (i.e. rod of resurrection).

Thank you.

Perhaps it’s something on my side, but it majes no harm to check…

When the henchman raises, by script or by a resurrección rod, it only keeps its body and arms equipment. Everything else gets Lost.

If I click on its dead body Everything is there. But if it then gets raised, it looses Everything and raises totally stripped down.

Any help?

Hello

At the end of battle the henchmen rise normally to me. I only raised them once mid battle with a rod of ressurection and had no problems. I would make a backup of the override and development folder, delete them and see if it happens again. Also make sure you copied the script correctly. In the upper right corner there is a button that copies the script to the clipboard. Once the script wasn’t compile for me because I copied by selecting the script manually.

It was not an script problem. I didn’t noticed that the follower’s items were set to “droppable”…

I’ve made a few tweaks to the original:

//::///////////////////////////////////////////////
//:: Henchman Death Script
//::
//:: NW_CH_AC7.nss
//::
//:://////////////////////////////////////////////

#include "nw_i0_generic"
#include "nw_i0_plot"
#include "x3_inc_horse"
#include "x0_i0_henchman"


void raise()
{
    // break the loop if became alive outside this script
    if(!GetIsDead(OBJECT_SELF))
    {
        return;
    }
    // find nearest alive enemy creature
    object oEnemy = GetNearestCreature(
        CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, 1,
        CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY
    );
    // get hench master
    object oPC = GetLocalObject (OBJECT_SELF, "NPC master");
    // is Enemy Close
    int iEnemyClose = FALSE;
    if(GetObjectSeen(OBJECT_SELF, oEnemy))
    {
        iEnemyClose = TRUE;
        //FloatingTextStringOnCreature("Seen by an enemy (" + GetName(oEnemy) + ") - staying dead", OBJECT_SELF);
    }
    // is Master Close
    int iMasterClose = FALSE;
    if (GetDistanceBetween (OBJECT_SELF, oPC) > 0.0 && GetDistanceBetween (OBJECT_SELF, oPC) < 5.0) {
        iMasterClose = TRUE;
    }
    // is Master Left
    int iMasterLeft = FALSE;
    if (GetArea(oPC) !=  GetArea(OBJECT_SELF)) {
        iMasterLeft = TRUE;
    }

// - If Master Left >> go home
    if (iMasterLeft) {
        SendMessageToPC (oPC, "You have abandoned a companion.");
        //Get Henchman Data
        object oHome = GetLocalObject (OBJECT_SELF, "NPC home");
        string sHenchmanResRef = GetResRef (OBJECT_SELF);
        string sHenchmanTag = GetTag (OBJECT_SELF);

        //Clear Item DB
        SetCampaignInt ("DB_TDLI_HEN",sHenchmanTag+"_inv_cnt",0);
        int iSlot;
        string sSlotDB;
        for (iSlot = 0; iSlot < 14; iSlot++) {
            sSlotDB = sHenchmanTag + "_slot_" + IntToString (iSlot);
            SetCampaignString ("DB_TDLI_HEN",sSlotDB, "");
        }

        //Spawn NPC at Home
        object oHenchMan = CreateObject (1,sHenchmanResRef,GetLocation(oHome),FALSE,"");
        DestroyObject (OBJECT_SELF, 1.0);
        DestroyObject (oHome, 1.0);
    } else {
// - If Master in area & Enemy Close >> Wait
        if (iEnemyClose) {
            DelayCommand(6.0, raise());
        } else {
// - If Master in area & Enemy !Close & Master Close >> Raise & Join
            if (iMasterClose) {
                ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection(), OBJECT_SELF);
                DelayCommand(0.0, AddHenchman(oPC));
            } else {
// - If Master in area & Enemy !Close & Master !Close >> Wait
                DelayCommand(6.0, raise());
            }
        }
    }
}

void main()
{
    // remember current master
    object oMaster = GetMaster();
    SetLocalObject (OBJECT_SELF, "NPC master", oMaster);


    SetLocalString(OBJECT_SELF,"sX3_DEATH_SCRIPT","x2_hen_death");
    if (HorseHandleDeath()) return;
    DeleteLocalString(OBJECT_SELF,"sX3_DEATH_SCRIPT");

    if (GetAssociateType(OBJECT_SELF) == ASSOCIATE_TYPE_HENCHMAN)
    {
       SetLocalInt(OBJECT_SELF, "X2_L_IJUSTDIED", 10);
       SetKilled(GetMaster());
       SetDidDie();
       object oHench = OBJECT_SELF;
        // * Take them out of stealth mode too (Nov 1 - BK)
        SetActionMode(oHench, ACTION_MODE_STEALTH, FALSE);
        // * Remove invisibility type effects off of henchmen (Nov 7 - BK)
        RemoveSpellEffects(SPELL_INVISIBILITY, oHench, oHench);
        RemoveSpellEffects(SPELL_IMPROVED_INVISIBILITY, oHench, oHench);
        RemoveSpellEffects(SPELL_SANCTUARY, oHench, oHench);
        RemoveSpellEffects(SPELL_ETHEREALNESS, oHench, oHench);
    }
    RemoveHenchman(GetMaster(), OBJECT_SELF);

    SetLocalObject (OBJECT_SELF, "NPC master", oMaster);
    // begin auto-raise loop with 6-second interval
    DelayCommand(6.0, raise());
}
1 Like