Author Topic: Suggestions on a Good Monster AI System?  (Read 1966 times)

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« on: August 13, 2010, 06:06:30 pm »


               I was wanting to build a selection of monsters for templates, and wanted to use a very nice / tested good monster AI which wouldn't just do the basic NWN AI... (Attack Attack Attack! / Cast All Best Spells In Order)

I saw one on a module where the NPC / Monster would randomly walk away from the PC if they were too close, I thought that was awesome...  (Very annoying but more realistic)

If anyone has any good Monster AI script to share, please do so in this thread..
               
               

               


                     Modifié par Genisys, 18 août 2010 - 03:06 .
                     
                  


            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #1 on: August 14, 2010, 07:08:50 pm »


               

Genisys wrote...

I was wanting to build a selection of monsters for templates, and wanted to use a very nice / tested good monster AI which wouldn't just do the basic NWN AI... (Attack Attack Attack! / Cast All Best Spells In Order)

I saw one on a module where the NPC / Monster would randomly walk away from the PC if they were too close, I thought that was awesome...  (Very annoying but more realistic)

Actually you can set different combat behaviors using SoU's combat AI.

Just stick this in the creature's OmnSpawn and it will run away if the PC comes within melee range:
#include "x0_i0_anims"
void main()
{
SetCombatCondition(X0_COMBAT_FLAG_RANGED);
}

The available conditions are:

X0_COMBAT_FLAG_AMBUSHER (move out of sight range of enemy and use invisibility or hide then attack)
X0_COMBAT_FLAG_COWARDLY (good for animals)
X0_COMBAT_FLAG_DEFENSIVE (use defensive feats like knockdown and expertise)
X0_COMBAT_FLAG_RANGED (creature moves away when enemy comes within melee range)

If I need anything more specialized I make my own combat AI by setting a local string on the creature called X2_SPECIAL_COMBAT_AI_SCRIPT with the value being the name of the AI script I want it to run.

-420
               
               

               


                     Modifié par 420, 14 août 2010 - 06:10 .
                     
                  


            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #2 on: August 14, 2010, 09:19:04 pm »


               So, from what your saying, if I like set  a string variable named (X2_SPECIAL_COMBAT_AI_SCRIPT ) on the monster from the OnSpawn Event for the monster, giving the variable a string of the name of the script which will fire, it will fire it when the monster spawns in or when??

Would this script fire every heartbeat?

More information needed for me, cause I'm new to scripting the Monster's AI..
               
               

               


                     Modifié par Genisys, 14 août 2010 - 08:20 .
                     
                  


            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #3 on: August 15, 2010, 03:05:45 am »


               

Genisys wrote...

So, from what your saying, if I like set  a string variable named (X2_SPECIAL_COMBAT_AI_SCRIPT ) on the monster from the OnSpawn Event for the monster, giving the variable a string of the name of the script which will fire, it will fire it when the monster spawns in or when??

Would this script fire every heartbeat?

More information needed for me, cause I'm new to scripting the Monster's AI..

The variable must be set in the blueprint, before the monster spawns. Edit the blueprint, click the "Advanced" tab then the "Variables" button.)

I believe it replaces the combat AI so it may override multiple events. If it replaced anything specific it's probably the monster's OnCombatRoundEnd event.

-420
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #4 on: August 15, 2010, 05:39:02 am »


               

420 wrote...

The variable must be set in the blueprint, before the monster spawns. Edit the blueprint, click the "Advanced" tab then the "Variables" button.)

I believe it replaces the combat AI so it may override multiple events. If it replaced anything specific it's probably the monster's OnCombatRoundEnd event.

-420



The varaiable does not have to be set in the blueprint.  It can be set at any time.  It can even be changed via scripting at any time that you want to change the creatures behavior.   

You are correct that it is in the on combat round that the changes take effect.  To narrow it down just a little more it is in the DetermineCombatRound function that the hook is set.  Right after the the first checks to see if the creature is peterfied or random walking it has this:

// ----------------------------------------------------------------------------------------
    // July 27/2003 - Georg Zoeller,
    // Added to allow a replacement for determine combat round
    // If a creature has a local string variable named X2_SPECIAL_COMBAT_AI_SCRIPT
    // set, the script name specified in the variable gets run instead
    // see x2_ai_behold for details:
    // ----------------------------------------------------------------------------------------
    string sSpecialAI = GetLocalString(OBJECT_SELF,"X2_SPECIAL_COMBAT_AI_SCRIPT");
    if (sSpecialAI != "")
    {
        SetLocalObject(OBJECT_SELF,"X2_NW_I0_GENERIC_INTRUDER", oIntruder);
        ExecuteScript(sSpecialAI, OBJECT_SELF);
        if (GetLocalInt(OBJECT_SELF,"X2_SPECIAL_COMBAT_AI_SCRIPT_OK"))
        {
            DeleteLocalInt(OBJECT_SELF,"X2_SPECIAL_COMBAT_AI_SCRIPT_OK");
            return;
        }
    }


 
               
               

               
            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #5 on: August 15, 2010, 03:19:27 pm »


               Ok, from what I see here, this script reads the variable on the NPC/Monster by the variable named "X2_SPECIAL_COMBAT_AI_SCRIPT" which is a string that you give the name of the script that you wish to fire, is this accurate?

Sweet... I like this, cause I can set up multiple scripts for multiple NPCs/Monsters, via executing another script within the script that fires by the bioware default scripts... (which is the first script the variable calls..)
Though I don't know if multiple scripts would have a benefit, an include script definitely would be nice here...

Now that I think about it, I'm going to get the major class of the NPC/Monster and determine which script set to fire based upon this information, this way I can determine how the NPC/Monster should act, especially based upon their level &/or class / or race..  (obviously a goblin is going to run and shoot, if they can..)

I can just imagine the PCs encountering a pack of goblins that scatter randomly and then start shooting at the PCs.. that would be so sweet!

Any chance anyone has some custom scripts / includes for monsters ai they care to share?
               
               

               


                     Modifié par Genisys, 15 août 2010 - 02:22 .
                     
                  


            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #6 on: August 15, 2010, 05:49:16 pm »


               

Genisys wrote...

Any chance anyone has some custom scripts / includes for monsters ai they care to share?

Here is a real simple script I wrote a long time ago for Shadowdancers. Each round it checks for a valid enemy in the area. If there is one then the Shadowdancer hides and attacks.


#include "nw_i0_generic"
#include "x2_inc_switches"
void main()
{
    // The following two lines should not be touched
    object oIntruder = GetCreatureOverrideAIScriptTarget();
    ClearCreatureOverrideAIScriptTarget();

    object oTarget = GetNearestSeenOrHeardEnemy();
    if(oTarget != OBJECT_INVALID)
    {
    ClearAllActions();
    ActionUseSkill(SKILL_HIDE, OBJECT_SELF);
    DelayCommand(1.0, ActionAttack(oTarget));
    }


    SetCreatureOverrideAIScriptFinished();
}

-420
               
               

               


                     Modifié par 420, 15 août 2010 - 04:49 .
                     
                  


            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #7 on: August 15, 2010, 07:47:50 pm »


               Thanks, I forgot about these. I will add them to my HR DM tools so the DM can change combat ai in game. '<img'>
               
               

               
            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #8 on: August 15, 2010, 07:50:25 pm »


               

In game, now there is food for thought...
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #9 on: August 15, 2010, 08:19:07 pm »


               Here is one for goblins:



//Goes OnUserDefined of a creature, or on perception, or hb.

#include "NW_I0_GENERIC"



void main()

{

  object oPC = GetLastPerceived();

  object oRoad = GetNearestObjectByTag ("Wp_Road");

  object oBase = GetNearestObjectByTag ("SkullPole");

  object oDummy = GetNearestObjectByTag ("Campfire");

  object oArea = GetArea(OBJECT_SELF);

  effect eRegenerate = EffectRegenerate(2, 3.0);

  int iHd = GetHitDice(oPC);



  location lWP = GetLocation(oRoad);

  location lWP1 = GetLocation(oBase);



  if (IsInConversation(OBJECT_SELF) || GetIsInCombat())

    return;

    if (GetIsEnemy (oPC))

     {

     ActionAttack(oPC);

     return;

     }

     if (GetDeity(oPC)== "Bocrewg")

     {

     DelayCommand(1.0,AssignCommand(OBJECT_SELF, PlayAnimation(ANIMATION_LOOPING_WORSHIP,0.5, 20.0)));

     SetIsTemporaryFriend(oPC, OBJECT_SELF, TRUE, 100.0 + iHd * 10);

     DelayCommand(10.0,AssignCommand(OBJECT_SELF, ActionForceFollowObject(oPC, 1.0 + iHd/6)));

     return;

     }



  //if fighting fight on.

  if  (GetWeather(oArea) == WEATHER_RAIN)

         {

         DelayCommand (1.0, ActionForceMoveToLocation(lWP1,TRUE));

         DelayCommand(3.0,AssignCommand(OBJECT_SELF, PlayAnimation(ANIMATION_LOOPING_SIT_CROSS,0.5, 20.0)));

         DelayCommand (10.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eRegenerate, OBJECT_SELF, 15.0));

         return;

         }



     string sWPTag1 = "wp_random";//seed tag of wp. wp's must be placed.

     string sRan = IntToString(d6()); //change dsize for more wp

     string sWPTag = sWPTag1 + sRan; //selects wp_random1-6

     location lWP2 = GetLocation(GetNearestObjectByTag(sWPTag));



      if (d100()<50)

      return;

     {

  ActionMoveToLocation(lWP, FALSE);

  DelayCommand (6.0, ActionMoveAwayFromLocation(lWP, FALSE));

  DelayCommand (12.0, ActionMoveToLocation(lWP2, FALSE));

      {

    if

     (GetDistanceToObject (oBase) < 6.0)

    return;

      if (GetDistanceToObject (oDummy) > 25.0)

       return;

   else



  switch( d4())

    {

   case 1: ActionMoveAwayFromObject(oPC, TRUE, 8.0);break;

   case 2: DelayCommand (2.0,ActionMoveToLocation(lWP,TRUE));break;

   case 3: ActionAttack(oDummy);break;

   case 4: DelayCommand(3.0,AssignCommand(OBJECT_SELF, PlayAnimation(ANIMATION_LOOPING_SIT_CROSS,0.5, 10.0)));

    }

}



}

}



Then for the ondamaged:



#include "nw_i0_generic"

#include "_prr_main"

void main()

{



       object oBase = GetNearestObjectByTag ("SkullPole");

       string sSoundName = "as_an_wolfhowl1";

       object oEnemy = GetLastDamager();



       object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC,OBJECT_SELF);

       location lWP = GetLocation(oBase);

       float fRange = 3.0;

       int nMaxInteger = 5;

       int nRandom = (nMaxInteger);

       int iHd =  GetHitDice(oPC);

       int nPercentage = 30 - iHd; //Percentage of HP the NPC has been damaged when they

       //will start to run

       int nDamage = d4(iHd/6);

       if ((GetPercentageHPLoss(OBJECT_SELF) > nPercentage) ||  (iHd > 4))

       PRR_AdjustHistoricalValue(oEnemy, OBJECT_SELF, -1);

      if (GetHasFeat (FEAT_SNEAK_ATTACK, oPC) &&  (GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_CRITICAL_HIT))&&(GetLocalInt (OBJECT_SELF, "SneakAttacked")!=1))



      {

   effect eDamage = EffectDamage (nDamage,  DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_ONE);

   effect eDeath = EffectDeath(TRUE, TRUE);

   ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, OBJECT_SELF);

   SetLocalInt (OBJECT_SELF, "SneakAttacked",1);

   DelayCommand (12.0, SetLocalInt (OBJECT_SELF, "SneakAttacked",0));

   if ((GetCurrentHitPoints(OBJECT_SELF) < 5) && (oEnemy == oPC))

   ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, OBJECT_SELF);

   SetLocalInt (oEnemy, "SneakKill", 1);

     }

         {

        ClearAllActions(TRUE);

        ActionMoveAwayFromObject(oEnemy, TRUE, fRange + nRandom + iHd);

        DelayCommand (3.0, SetCommandable(FALSE,OBJECT_SELF));

        DelayCommand (6.0, SetCommandable(TRUE,OBJECT_SELF));

        DelayCommand (6.4, ActionEquipMostDamagingRanged());

        DelayCommand (6.8, ActionAttack (oPC));

        DelayCommand (12.0, ActionForceMoveToLocation(lWP, TRUE));

        if (d20(2)> 25)

        DelayCommand (25.0, ExecuteScript("_combatvanish",OBJECT_SELF));

         return;



            switch(d4())

                       {

                       case 1: ActionAttack (oEnemy);break;

                       case 2: PlaySound(sSoundName); break;//calling for wolves

                       case 3: TalentBuffSelf(); break;

                       case 4: UseStealthMode(); break;

                        }

       }

}





Of course you don't have all those references to waypoints but you get the idea.
               
               

               
            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #10 on: August 16, 2010, 08:26:06 am »


               I see some gross errors in that script:

if (GetIsEnemy (oPC))

{

ActionAttack(oPC);

return;

}

If it's a PC just attack and stop checking everything else... this would be bad..


I'd rework that script with a custom Prototype Function, which would go something like this...

void  AssignCombatAI(object oPC, int nToDo)
{
  //where   nToDo = the Assigned Action  (This of course allows for delays and tidies code)
  //Obviously your going to need oPC to tell OBJECT_SELF (The Monster) what to do to what target..

  switch(nToDo)
  {
    case 0: //do Nothing
    break;

    case 2:
    {
      //Do This Instead
     } break;

     case 2:
    {
      //Do This Instead
     } break;

}

//End Prototype
}


This:    if (GetDeity(oPC)== "Bocrewg")

of course ffbj is freaking hillarious.. '<img'>
               
               

               


                     Modifié par Genisys, 16 août 2010 - 07:36 .
                     
                  


            

Legacy_Jargh193

  • Newbie
  • *
  • Posts: 36
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #11 on: August 18, 2010, 01:36:53 am »


               I like 420's first post, but would be fun to make it a random check onspawn to choose which flag to use for each monster. Always fun to make things random so even the DM's and builders can't figure it out '<img'>
               
               

               
            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #12 on: August 18, 2010, 01:59:37 pm »


               That's funny Jargh193... I'm still laughing.. .lol!
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #13 on: August 18, 2010, 02:07:29 pm »


               Genisys, for your first answer. I used to used Jasperr's AI, but several TMI was happening. Also his AI didn't handled custom spells - which the default one does handle (was quite suprise to me). In those times I learned how to write my own AI and today, same as 420, I use default AI and if I need something, I write it. I could maybe recommend you the Jasperre's ai, but its really not for all monsters, I woul use it only for togh ones or mages.
               
               

               
            

Legacy_Genisys

  • Hero Member
  • *****
  • Posts: 961
  • Karma: +0/-0
Suggestions on a Good Monster AI System?
« Reply #14 on: August 18, 2010, 02:25:44 pm »


               Magic Using Monsters would definitely be a needed AI, for the default AI on mages is rather bad in my professional opinion, they should choose based upon situation, not just cast best to least effective spells in concession, where Fighting Monsters AI on the other hand, other than Archers, is not really needed as much...  (Making Archers to change weapons for close combat or run away would is awesome)

Some builders pre-buff monsters before the encounter happens, which to me is cheating if the PCs have to spend time buffing, because it takes away the advantage of the PC, furthermore, if you give the monsters a Dispel, all those buffs go bye bye, which is completely lame... But that's not really relevant to the discussion at hand, and is probably best left for another post / discussion altogether..

Does anyone have any Caster AI scripts for monsters?

I think someone suggested how to make archers above.. thanks again..
               
               

               


                     Modifié par Genisys, 18 août 2010 - 01:27 .