Author Topic: Script Request for a creature confined within a confined trigger.  (Read 368 times)

Legacy_Uther Ver Magnus

  • Newbie
  • *
  • Posts: 8
  • Karma: +0/-0


               

I can't seem to get the Lilac Soul Script Generator to do what I'm wanting.  Can it do this?  I am wanting to keep a creature confined to a defined area.  When in pursuit of a player,  If the player decides to run, the creature will pursue.  As the player exits the boundary of a generic trigger, the creature will be stopped in its tracks.  It can try, but must not be able to leave the area.  It will just return to random walk its confined area.  


 


Ok, here it is in full.  This is a multiple script layout.  I will lay down a generic trigger encompassing a maze.  (Script Needed) As the player enters the maze a creature will be spawned into a random location in the maze.  The script must check if a creature has been spawned already.  I don't want multiple "boss" creatures randomly walking around. Oh yeah, need a random walk script as well.  Now, if the player happens upon the creature, a battle ensues.  (Script Needed) Upon death of the creature, unbeknownst to the player, it will be respawned, again in a random location in the maze.   Now back to the beginning of this post.  If the battle happens to be to much for the player, and chooses to turn tail and run.  They can exit the maze all they want, but the creature must not be able to.  I want the creature to return to its cursed domain and return to randomly walk.  


 


Thank you to anyone who helps.


 


               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #1 on: April 11, 2014, 08:13:21 pm »


               

**bump**



               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #2 on: April 12, 2014, 11:25:11 am »


               

Well, I am probably not the most experienced at this type of script (not having much experience with the NPC AI) and I am not fully certain what is wanted here. If the boss can just be teleported back to some starting point in the maze, then this sounds pretty straightforward. Since I may be the first to provide a script, I will assume that is true.


 


The idea is to just draw a trigger around the area the boss is to be confined to and make sure a his starting point waypoint and patrol waypoints are in it somewhere. The OnEnter script checks that there isn't already a boss on this map and then spawns one. The OnExit script for the trigger clears his action queue and moves him to that waypoint. (I don't know if some further fiddling with his AI priorities would be necessary to get him to leave the PC alone until the PC gets near again.) Use ActionJumpToLocation() on the waypoint's location to move the boss.


 


I am also assuming the OP is using the walkway system noted in the script. I am not an expert at that, either, but it seems to be pretty well known and the link I provided has some examples and troubleshooting advice.


 


So, draw the trigger around the maze area, add the patrol waypoints, then try the following as the OnEnter and OnExit scripts. Note that the constants near the tops of the scripts (where I refer to a standard NWN Minotaur Chief and his first walk waypoint) should be customized to the particular boss.


 


BTW, I chose randomly among the patrol waypoints for the "random" spawn (and respawn) points. One could certainly set up separate waypoints, if those aren't random enough. Also, I used a function to count those waypoints, for flexibility. But, if the number is known ahead of time, the call to CountWalkpoints could be replaced by that number.



// MazeBossEnter.nss
// The OnEnter script for http://forum.bioware.com/topic/501623-script-request-for-a-creature-confined-within-a-confined-trigger/

// Set these for the boss. Same as OnExit script
const string MAZEBOSSTAG = "NW_MINOTAURBOSS";       // The boss' tag
const string MAZEBOSSRESREF = "nw_minotaurboss";    // The boss' ResRef
const string MAZEBOSSSPAWNTAG = "nw_minotaurboss";  // The tag of the waypoint where the boss will spawn

// only counts up to 99
int CountWalkpoints()
    {
    int nWPTest = 0;
    object oWP;
    string sWPTag = "WP_" + MAZEBOSSTAG + "_01";
    oWP = GetObjectByTag(sWPTag);
    while ( GetIsObjectValid(oWP) )
        {
        nWPTest++;
        if (nWPTest<9)
            sWPTag = "WP_" + MAZEBOSSTAG + "_0" + IntToString(nWPTest+1);
        else
            sWPTag = "WP_" + MAZEBOSSTAG + "_" + IntToString(nWPTest+1);
        oWP = GetObjectByTag(sWPTag);
        }
    return nWPTest;
    }

void main ()
    {
    object oPC = GetEnteringObject();
   
    // Check the PC
    if ( !GetIsObjectValid(oPC) )
        return;
    if ( !GetIsPC(oPC) )
        return;
    if ( GetIsDM(oPC) )
        return;
   
    // Check if we already have a boss here
    object oBoss = GetObjectByTag(MAZEBOSSTAG);
    if ( GetIsObjectValid(oBoss) && GetArea(oBoss)==GetArea(OBJECT_SELF) )
        return;

    // Still here? Spawn the boss
    // Using walkpoints for "random" location.
    string sWPTag;
    int nLocIndex = Random(CountWalkpoints()) + 1;
    if (nLocIndex<10)
        sWPTag = "WP_" + MAZEBOSSTAG + "_0" + IntToString(nLocIndex);
    else
        sWPTag = "WP_" + MAZEBOSSTAG + "_" + IntToString(nLocIndex);
    location lSpawnPoint = GetLocation(GetObjectByTag(sWPTag));
    oBoss = CreateObject(OBJECT_TYPE_CREATURE, MAZEBOSSRESREF, lSpawnPoint);
    }


// MazeBossExit.nss
// The OnExit script for http://forum.bioware.com/topic/501623-script-request-for-a-creature-confined-within-a-confined-trigger/

#include "x0_i0_walkway"

// Set these for the boss. Same as OnEnter script
const string MAZEBOSSTAG = "NW_MINOTAURBOSS";       // The boss' tag
const string MAZEBOSSRESREF = "nw_minotaurboss";    // The boss' ResRef
const string MAZEBOSSSPAWNTAG = "nw_minotaurboss";  // The tag of the waypoint where the boss will spawn

void main ()
    {
    object oPC = GetExitingObject();
   
    // Check the PC
    if ( !GetIsObjectValid(oPC) )
        return;
    if ( !GetIsPC(oPC) )
        return;
    if ( GetIsDM(oPC) )
        return;
   
    // Check that we have a boss and he is here
    object oBoss = GetObjectByTag(MAZEBOSSTAG);
    if ( !GetIsObjectValid(oBoss) || GetArea(oBoss)!=GetArea(OBJECT_SELF) )
        return;

    // Still here? Move the boss to his start point.
    location lSpawnPoint = GetLocation(GetObjectByTag(MAZEBOSSSPAWNTAG));
    AssignCommand(oBoss, ClearAllActions(TRUE));
    AssignCommand(oBoss, ActionJumpToLocation(lSpawnPoint));
    AssignCommand(oBoss, WalkWayPoints());  // see http://nwn.wikia.com/wiki/Waypoints_used_with_walkwaypoints
    }

For the OnDeath handler, this just checks that any boss creature with the specified tag in the area is dead and then respawns that boss. One could certainly do this with a delay or with some effects.



// MazeBossDeath.nss
// The OnDeath script for http://forum.bioware.com/topic/501623-script-request-for-a-creature-confined-within-a-confined-trigger/

// Set these for the boss. Same as OnEnter script
const string MAZEBOSSTAG = "NW_MINOTAURBOSS";       // The boss' tag
const string MAZEBOSSRESREF = "nw_minotaurboss";    // The boss' ResRef
const string MAZEBOSSSPAWNTAG = "nw_minotaurboss";  // The tag of the waypoint where the boss will spawn

// only counts up to 99
int CountWalkpoints()
    {
    int nWPTest = 0;
    object oWP;
    string sWPTag = "WP_" + MAZEBOSSTAG + "_01";
    oWP = GetObjectByTag(sWPTag);
    while ( GetIsObjectValid(oWP) )
        {
        nWPTest++;
        if (nWPTest<9)
            sWPTag = "WP_" + MAZEBOSSTAG + "_0" + IntToString(nWPTest+1);
        else
            sWPTag = "WP_" + MAZEBOSSTAG + "_" + IntToString(nWPTest+1);
        oWP = GetObjectByTag(sWPTag);
        }
    return nWPTest;
    }

void main ()
    {
    object oPC = GetEnteringObject();
   
    // Check the PC
    if ( !GetIsObjectValid(oPC) )
        return;
    if ( !GetIsPC(oPC) )
        return;
    if ( GetIsDM(oPC) )
        return;
   
    // Check if we already have a boss here
    if ( GetIsObjectValid(oBoss) && GetArea(oBoss)==GetArea(OBJECT_SELF) )
        if ( !GetIsDead(oBoss) )
            return;

    // Still here? Spawn the boss
    // Using walkpoints for "random" location.
    string sWPTag;
    int nLocIndex = Random(CountWalkpoints()) + 1;
    if (nLocIndex<10)
        sWPTag = "WP_" + MAZEBOSSTAG + "_0" + IntToString(nLocIndex);
    else
        sWPTag = "WP_" + MAZEBOSSTAG + "_" + IntToString(nLocIndex);
    location lSpawnPoint = GetLocation(GetObjectByTag(sWPTag));
    oBoss = CreateObject(OBJECT_TYPE_CREATURE, MAZEBOSSRESREF, lSpawnPoint);
    }

Anyway, it's getting a little late here and my time to test this is minimal, but that's a first attempt. I expect others will know better ways of doing this, but this should get the ball rolling.



               
               

               
            

Legacy_kalbaern

  • Hero Member
  • *****
  • Posts: 1531
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #3 on: April 13, 2014, 12:44:08 am »


               

This might be simpler. Place it in the OnExit event of your trigger.


 


 


 


void main()

{


object oExiting = GetExitingObject();


if( !GetIsObjectValid( oExiting) || (GetTag( oExiting) != "TAG_OF_NPC")) return;//replace with the tag of your NPC

  {


   AssignCommand(oExiting, ClearAllActions(TRUE));//make them stop fighting and obey the next command


   DelayCommand (0.1, AssignCommand(oExiting, ActionJumpToLocation(GetLocation(GetNearestObjectByTag("WP_BOSS_STAY")))));//set a waypoint tagged as WP_BOSS_STAY where the NPC should return to


   }

}

 


I'd avoid using other actions than an actual "jump" as they tend to get interupted when the NPC still sees the hostile PC or its perception or other events fire and reset the commands. Just jump 'em back and it'll work better.

 



               
               

               
            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #4 on: April 13, 2014, 09:00:00 am »


               The actions should work more reliably like this:
 
void DoStuff();  // Name this function whatever you like throughout

void main()
 {

 object oExiting = GetExitingObject();

 if( !GetIsObjectValid( oExiting) || (GetTag( oExiting) != "TAG_OF_NPC")) return;//replace with the tag of your NPC
   {
      AssignCommand(oExiting, DoStuff());    
   }
 }

void DoStuff
{
  ClearAllActions(TRUE);//make them stop fighting and obey the next command
  ActionForceMoveToLocation(GetLocation(GetNearestObjectByTag("WP_BOSS_STAY"))));//set a waypoint tagged as WP_BOSS_STAY where the NPC should return to
  ActionDoCommand(SetCommandable(TRUE));
  SetCommandable(FALSE);
}
That way, the AI doesn't kick in until the boss has returned to the waypoint. They will try to walk, but jump if that times out.
               
               

               
            

Legacy_Squatting Monk

  • Hero Member
  • *****
  • Posts: 776
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #5 on: April 13, 2014, 08:45:31 pm »


               

That way, the AI doesn't kick in until the boss has returned to the waypoint. They will try to walk, but jump if that times out.


Good idea, but it seems like this could be exploited by a PC who comes back to attack the boss before he gets back to a commandable state. Should probably add a check for that in any combat events.
               
               

               
            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #6 on: April 13, 2014, 10:57:54 pm »


               True. Maybe easier to detect a player entering the trigger?


Hopefully the boss has a ranged attack, too - otherwise a player can spam missiles from outside of the containment area.
               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #7 on: April 13, 2014, 11:44:12 pm »


               

It seems like teleporting the boss back toward the center of the maze (and presumably out of line of sight) would work well for avoiding the sort of exploit where the PC can attack a vulnerable boss as he returns to base. I don't recall that the OP was specific in saying the boss had to walk back into the maze, though I can imagine situations where that might be desired.


 


Another potential approach is to design the return zone so that the boss starts heading back to his base at a point where he doesn't have to walk far to be out of line-of-sight. In other words, he starts walking back right as (or before) emerging from the maze, where he has cover from a PC who has left the maze.



               
               

               
            

Legacy_Uther Ver Magnus

  • Newbie
  • *
  • Posts: 8
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #8 on: April 14, 2014, 01:26:22 am »


               

Well, that's kind of what I'm looking for.  Someone might figure that out and try that.  But upon death of the creature, it will respawn at a random location withing the confined area.  Unbeknownst to the player.  That way when the player reenters the maze, they think the coast is clear.  But..... Nope.


 


Ok,  I must admit.  About 10yrs ago I had all this worked out.  Had the scripts that I wanted and they did exactly what I wanted.  But that laptop crashed and I lost alot of data.  Not just NWN data.


 


When the cursed creature reaches the boundary of the trigger, I don't want the creature to be jumped or teleported anywhere.  I want it to stop pursuit (clear all actions).  Even if it reaquires the player with its (on perception)script.  It must not be able to exit the boundary.  It will turn around,, walk back into the maze.  Begin it's random walk script.  There is a way to get creatures to random walk without walk waypoints.    



               
               

               
            

Legacy_MrZork

  • Hero Member
  • *****
  • Posts: 1643
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #9 on: April 14, 2014, 02:32:23 am »


               

The scripts I posted above, combined with the other points people have made should do what you want. Have the boss return to his starting area using the DoStuff function Proleric posted, which clears the action queue and forces a walk while disallowing other actions to be added to the boss' queue until he gets back.


 


ActionRandomWalk() will cause a creature to walk randomly until he is cleared or has a higher priority task generated. You could add that to the end of DoStuff. But, there is nothing wrong with using walkpoints and it may be the easiest way to find legitimate respawn points when the boss is killed and respawns.



               
               

               
            

Legacy_Uther Ver Magnus

  • Newbie
  • *
  • Posts: 8
  • Karma: +0/-0
Script Request for a creature confined within a confined trigger.
« Reply #10 on: April 14, 2014, 02:36:29 am »


               

K, Thanks all.  I appreciate it.  I'll see how it works.