Author Sticky: Post Working Scripts Here
Ojos Posted: Thursday, 11 July 08:29PM
1. Suggested (not required) script name: h_command_ai

2. This script performs all of the basic henchman associate commands, and is contained in only one script slot for a character.

3. Known Issues:

This particular version of the script is not meant to be used with henchmen who use ranged weapons, or are pure magic users (wizards, sorcerers).

For the voice chat to play, you must assign your creature a sound set.

For henchmen to use their healing skill, they must have the standard "healers kit +1" in their inventory.

Well, I sifted through this thread and I was surprised to see no one has posted a henchman basic command script?

4. Here is mine:


Thanks again Rhodan and Sweeney Todd for your help with getting this thing optimized.

NWScript:
// Written by Ojos

//associate command variables

int nlastheard = GetLastAssociateCommand (OBJECT_SELF);

int nfollowme = ASSOCIATE_COMMAND_FOLLOWMASTER;

int nstandground = ASSOCIATE_COMMAND_STANDGROUND;

int nattack = ASSOCIATE_COMMAND_ATTACKNEAREST;

int nguard = ASSOCIATE_COMMAND_GUARDMASTER;

int nheal = ASSOCIATE_COMMAND_HEALMASTER;

// specific objects

object oleader = GetMaster ();

object okit_1 = GetObjectByTag ("NW_IT_MEDKIT001");

object oenemy = GetNearestCreature (CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oleader);

// Heal variables

int nmaxhp = GetMaxHitPoints (oleader);

int nhp = GetCurrentHitPoints (oleader);



void main()

{

int nuser = GetUserDefinedEventNumber();

       switch (nuser)

       {

        case 1002:

        if (GetIsObjectValid (oleader))

            {

             ActionForceFollowObject(oleader, 3.5);

            }

        break;

        case 1003:

        if (GetIsObjectValid (oenemy) == FALSE)

        {

        ActionForceFollowObject(oleader, 3.5);

        }

        break;

        case 1004:

    ///////////////////1004 BEGIN///////////////////

        SetAssociateListenPatterns ();



    if (nlastheard == nfollowme)

     {

        ClearAllActions();

        //speech

        ActionSpeakString ("I will follow you");

        ActionWait (1.0);

        PlayVoiceChat (VOICE_CHAT_CANDO, OBJECT_SELF);

        ActionForceFollowObject (oleader, 3.5);

        return;

     }



    if (nlastheard == nstandground)

     {

        ClearAllActions();

        //speech

        ActionSpeakString ("I will wait here");

        ActionWait (1.0);

        PlayVoiceChat (VOICE_CHAT_YES, OBJECT_SELF);

        ActionForceFollowObject (OBJECT_SELF);

        return;

     }



    if (nlastheard == nattack)

     {

        ClearAllActions();

        //speech

        ActionSpeakString ("Charge!!!");

        ActionWait (1.0);

        PlayVoiceChat (VOICE_CHAT_ATTACK, OBJECT_SELF);

                    if (GetIsObjectValid (oenemy))

                    {

                      ActionAttack (oenemy);

                    }

       return;



     }





    if (nlastheard == nguard)

     {

        ClearAllActions();

        //speech

        ActionSpeakString ("I will guard you!");

        ActionWait (1.0);

        PlayVoiceChat (VOICE_CHAT_YES, OBJECT_SELF);

         ActionForceMoveToObject (oleader, TRUE, 0.0f);

       DelayCommand (2.0, ActionAttack(GetAttackTarget (oleader)));

        return;

     }





    if (nlastheard == nheal)

     {

        ClearAllActions();

      if (nhp != nmaxhp)

      {

         //speech

         ActionSpeakString ("I will heal you!");

            ActionWait (1.0);

            PlayVoiceChat (VOICE_CHAT_CANDO, OBJECT_SELF);



        //1

        if (nhp != nmaxhp)

        {

          ActionCastSpellAtObject (SPELL_HEAL, oleader, METAMAGIC_NONE);

        }

        //2

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_HEALING_CIRCLE, oleader, METAMAGIC_NONE);

        }

        //3

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_MASS_HEAL, oleader, METAMAGIC_NONE);

        }

        //4

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_CURE_CRITICAL_WOUNDS, oleader, METAMAGIC_NONE);

        }

        //5

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_CURE_SERIOUS_WOUNDS, oleader, METAMAGIC_NONE);

        }

        //6

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_CURE_MODERATE_WOUNDS, oleader, METAMAGIC_NONE);

        }

        //7

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_CURE_LIGHT_WOUNDS, oleader, METAMAGIC_NONE);

        }

        //8

        if (nhp != nmaxhp)

        {

        ActionCastSpellAtObject (SPELL_CURE_MINOR_WOUNDS, oleader, METAMAGIC_NONE);

        }

              if (nhp != nmaxhp)

              {



            ActionUseSkill (SKILL_HEAL, oleader, 0, okit_1);

            ActionWait (3.0);

            ActionTakeItem (okit_1, OBJECT_SELF);

            ActionWait (1.0);

            DelayCommand (4.5, ActionForceFollowObject (oleader, 3.5));

            return;

             }

      }

        ActionSpeakString (" You are healthy");

          DelayCommand (2.0, ActionForceFollowObject (oleader, 3.5));

            return;



     }

     //////1004 END/////////////



       }

 }



To get this to work, simply copy and paste it into a blank script (make sure you don't have two void mains).
Then put it in your creature's "user defined event" slot.


You only have two other things you need to do now.
In the default "on spawn" script, uncomment (remove the "//" from these lines:

NWScript:
SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT);

SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT);

SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT);



The last thing you need to do is add the henchman to your party.

Create a script, and put this script in an "actions taken"
option in the conversation editor.

NWScript:
void main()

{

AddHenchman (GetPCSpeaker(), OBJECT_SELF);

ActionForceFollowObject (GetPCSpeaker(), 2.0);

}



There, you should have a working henchman that responds to the basic commands!

1. Suggested (not required) script names: h_rogue_ai_traps
& h_rogue_ai_locks

2. Here are my henchmen disarm trap and lock picking scripts, as a bonus.

3. Known Issues: These scripts are designed to detect a trap or lock on the NEAREST object to their master, the pc. If they aren't working, move your pc closer to the trapped/locked object, and talk to your henchman again.

The best method of activating these scripts is by putting them in the "actions taken" portion of the conversation editor.

Script for disarming a trap & and picking a lock, if it has one:

NWScript:
//Written by Ojos

//initiate through dialogue

object oleader = GetMaster ();

object otrap = GetNearestTrapToObject(oleader, TRUE);

// for a locked chest that has a trap on it

int nlock = GetLocked (otrap);



int ntrap_rank = GetTrapDisarmDC (otrap);

int nlock_rank = GetLockUnlockDC (otrap);

int nh_trap = GetSkillRank (SKILL_DISABLE_TRAP, OBJECT_SELF) + 20;

int nh_lock = GetSkillRank (SKILL_OPEN_LOCK, OBJECT_SELF) + 20;



void main()

{

//locked AND trapped

if (GetIsObjectValid (otrap))

 {

ClearAllActions();

ActionSpeakString ("I have found the box");

   ActionWait (1.0);

    if (nh_trap >= ntrap_rank)

   {

ActionUseSkill (SKILL_DISABLE_TRAP, otrap, 0, OBJECT_INVALID);



    if (nlock == TRUE)

      {

     ActionSpeakString ("I have found the lock");

        ActionWait (1.0);

        if (nh_lock >= nlock_rank)

    {

      ActionUseSkill (SKILL_OPEN_LOCK, otrap, 0, OBJECT_INVALID);

                return;

                }

      ActionSpeakString ( "I can't unlock this");



           }

                  return;

                }

     ActionSpeakString ("I can't disable this trap");

         }

}



Script for picking something that is only locked (or the trap has just not been detected):

NWScript:
//Written by Ojos

//initiate through dialogue

object oleader = GetMaster();

object odoor = GetNearestObject (OBJECT_TYPE_DOOR, oleader);

object oplace = GetNearestObject (OBJECT_TYPE_PLACEABLE, oleader);



int nldoor = GetLocked(odoor);

int nlplace = GetLocked (oplace);

int nlock_rank_d = GetLockUnlockDC (odoor);

int nlock_rank_p = GetLockUnlockDC (oplace);

int nh_lock = GetSkillRank (SKILL_OPEN_LOCK, OBJECT_SELF) + 20;

void main()

{

 // door AI

    if (GetIsObjectValid (odoor))

        {



    if (nldoor == TRUE)

      {

    ClearAllActions ();

   ActionSpeakString (" I have found a locked door");

     ActionWait (1.0);

       if (nh_lock >= nlock_rank_d)

         {

       ActionUseSkill (SKILL_OPEN_LOCK, odoor, 0, OBJECT_INVALID);

        return;

          }

    ActionSpeakString ( "I can't unlock this");

            }

        }

//placeable AI



      if (GetIsObjectValid (oplace))

        {



            if (nlplace == TRUE)

            {

    ClearAllActions ();

   ActionSpeakString ("I have found a locked object");

    ActionWait (1.0);

     if (nh_lock >= nlock_rank_p)

        {

   ActionUseSkill (SKILL_OPEN_LOCK, oplace, 0, OBJECT_INVALID);

       return;

                }

     ActionSpeakString ( "I can't unlock this");





            }

        }



}



Hope this helps.

UPDATE

If anything is unclear, please look at my original post on page 22 of this topic.

1. Suggested (not required) r_command_ai

2. VERY basic AI for keeping ranged weapon and magic user henchmen away from physical combat.

3. Known Issues: This must be used with my original henchman script (last post on page 22).

This AI should not be used with henchmen who are primarily a fighter class, or one that you wish to enter melee combat.

Thanks go to Vlad755 for his post here on the "SetAssociateState( NW_ASC_USE_RANGED_WEAPON, TRUE)" function:

Click Here

4. Update your on spawn script (that has the three lines already uncommented from earlier) by placing this line of code directly after the void main and bracket.

NWScript:
SetAssociateState( NW_ASC_USE_RANGED_WEAPON, TRUE);


Now, go to my main script, and scroll down until you find "case 1003". It should look like this.

NWScript:
case 1003:

        if (GetIsObjectValid (oenemy) == FALSE)

        {

        ActionForceFollowObject(oleader, 3.5);

        }

        break;


Clear out those lines and replace it with this.

NWScript:
case 1003:



        ActionMoveAwayFromObject (oleader, TRUE, 5.0);



        if (GetIsObjectValid (oenemy) == FALSE)

        {

        ActionForceFollowObject(oleader, 3.5);

        }

        break;


This should help keep ranged users out of combat, and have magic users flee a certain distance if they move in close to cast spells on you.



PS: I created a nice script that raised a few alerts, equipped any weapon and shield in the henchman's inventory for a time, and moved them a nicer distance away if they were ever damaged by something.

Unfortunately, after several fruitless hours of trying to beat the 6 second combat round interval, I've had to drop it for now.

The script works, it's just not graphically pleasing (lots of stutters). If anyone has a way of getting a script ahead of the combat round, I'm all ears. (The on damaged and physical attacked slots were of no help).

Hope this helps.