Aller au contenu

Photo

WalkWaypoints and Scripted Waypoints (Repost)


  • Veuillez vous connecter pour répondre
16 réponses à ce sujet

#1
_Knightmare_

_Knightmare_
  • Members
  • 643 messages
Didn't want this info lost from the old Bio boards:

=======================================================================

Originally Posted By Charles Mead 06 Nov 2006 (Bold Type added)

Here's some info on a new feature called Scripted Waypoints.

Scripted waypoints builds on the current waypoints system by making the arrival at each waypoint call a script. There are no special requirements for preparing this – it will work with any NPC using the regular default scripts and any new or previously placed set of walkway points.

Quick refresher of the standard waypoint system:
Creatures will automatically walk along a sequence of waypoints that are tagged according to the following convention: “WP_NPCTag_##”. The NPC will begin the journey at waypoint 1 and continue traveling sequentially to waypoint n, and then back again in reverse.

Basic Useage:
In the new “scripted waypoint” system, whenever a creature reaches a waypoint, it calls a script that is named very similarly to the tag used for the waypoints, like this: “wp_NPCTag”. Notice there is just one script for the entire set of waypoints. If the script does not exist, then nothing additional happens and the NPC simply walks back and forth through the set of waypoints.

Below are some examples of “scripted waypoints” scripts:

Example 1.
This script tells the NPC to stop at every waypoint and face in the direction the waypoint is facing and pause 1 second before continuing to the next waypoint.
Notice the inclusion of “ginc_wp” which has a number of helpful functions such as FaceAndPause().

#include "ginc_wp"
void main()
{
int iCurrentWP = GetCurrentWaypoint();
FaceAndPause(iCurrentWP, 1.0f);
}

Note how we call GetCurrentWaypoint() which returns the waypoint we have just reached. This will typically always be the first thing called in a “scripted waypoints” script.


Example 2.
This is a more complex script that completely overrides the normal waypoint behavior and demonstrates how each waypoint can be individually scripted. It accomplishes the following:
When the NPC reaches waypoint 1, he will sit down for a few seconds, and then randomly travel to one of the other waypoints in the set other than the first.
When the NPC reaches waypoint 2, he will play a “get low” animation, and then proceed to waypoint 1.
When the NPC reaches waypoint 3, he will simply head back to waypoint 1.
If there are more than 3 waypoints in the set, then when the NPC reaches one of those he will behave in the default way.

#include "ginc_wp"

void main()
{
int iCurrentWP = GetCurrentWaypoint();
int iNextWP;
switch (iCurrentWP)
{
case 1:
iNextWP = Random(GetNumWaypoints()-1) + 2;
SetNextWaypoint(iNextWP);
ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0, 7.0);
break;
case 2:
SetNextWaypoint(1);
ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);
break;
case 3:
SetNextWaypoint(1);
break;
}
}

Note in this example the use of SetNextWaypoint(). The “next” waypoint is the one the NPC is enroute to. SetNextWaypoint() allows us to override this and redirect the NPC to an alternate waypoint.

The script template “wp_tag” is available in the script templates directory in source safe. Simply copy and paste it with the proper script name, replacing the word “tag” with the tag of the creature that will be walking waypoints.


*Advanced Usage*
How to have two or more creatures with different tags walk the same set of waypoints:

To override the initial waypoint set a creature uses, simply set a local string variable “WP_TAG” on the creature with the value of the desired waypoint set to use. So, if you have a bear waypoint set for a creature tagged “bear”, you could get a chicken to also walk these waypoints by setting the chicken's local variable WP_TAG to “bear”.
Note that this variable is only checked when the creature is first spawned, so changing this value via script will have no effect.

How to change the set of waypoints a creature walks dynamically:
You can change the set of waypoints a creature walks at any time via script using this function:
object SetWWPController(string sWalkWayPointsTag, object oCreature=OBJECT_SELF);

So from the previous example, we could have our chicken walk the bear’s waypoints by calling this function in script:
SetWWPController(“bear”);


How to pause/restart a creature walking waypoints.
To stop a creature from walking waypoints, use:
SetWalkCondition(NW_WALK_FLAG_PAUSED, TRUE);

You may also want to clear all actions, otherwise, the creature will still complete his pending actions which will take him to whatever the next waypoint is.

To Restart a creature walking waypoints, use:
SetWalkCondition(NW_WALK_FLAG_PAUSED, FALSE);

The creature should get started on his next heartbeat.


How to create a road network:
The basic outline for a script like this is available in the script template “wp_road_walker” and reads as follows:

#include "ginc_wp"

const int REDIRECTOR_WP = 1;

void main()
{
int iCurrentWP = GetCurrentWaypoint();// where we are
int iNextWP;
switch (iCurrentWP)
{
case 1: 
// Node 1 should be placed off somewhere out of the way. This is where the creatures
// will hang out in between reaching the end of the path and starting on a new path.
// Creatures will change their appearance in between travels.

// 1st param is the list of nodes they may reappear at. Must follow the pattern XX,YY,ZZ...
// 2nd param is the length of time to wait before reappearing.
StandardRedirectorNode("02,03", 5.0f);
break;
case 2:
// Nodes 2 on up define the network the road walkers travel. They will never return to the node
// they just came from. When they reach an end node (typically a door or a route out of the area)
// they will be be "redirector node" - typically node 1.

// 1st param is the list of nodes they may travel to. Must follow the pattern XX,YY,ZZ...
// (end nodes are those with only 1 element in the list)
// 2nd param is the redirector WP
StandardRoadNetworkNode("03", REDIRECTOR_WP);
break;

case 3:
StandardRoadNetworkNode("02", REDIRECTOR_WP);
break;

}
}

Where can I learn more about other thing I can do?
Many useful functions are listed in the prototypes of the include file “ginc_wp”.

Modifié par _Knightmare_, 17 août 2010 - 11:49 .


#2
rjshae

rjshae
  • Members
  • 4 477 messages
Rather than setting up a ton of walk waypoint paths for different character movements through a town, I decided to use the same set for everybody and just vary the set of waypoints on a per-character basis. This eliminates a lot of waypoint redundancy and allows a more random-looking movement, but it also requires more customization per character (which is okay for my purposes). Attached below is the code I used, which is basically an add-on to the "x0_i0_walkway" include file. It seems to work okay, and I've been able to apply the script waypoints technique with the custom waypoint sets.

// ww_inc_walkway
/*
  The following routines allow a custom set of waypoints
  to be configured as the walk waypoints for a creature.
  The InitCustomWWPController routine should be called
  first, followed by AddCustomWaypoint for each waypoint.
  Use ClearCustomWaypoints to clear the custom walk
  waypoints and reload the default waypoints.
*/
#include "x0_i0_walkway"

// Prototypes

object InitCustomWWPController( object oCreature=OBJECT_SELF, string sScriptSuffix = "" );
int AddCustomWaypoint( object oCreature, string sCustomTag );
int SetCustomWaypoints( object oCreature=OBJECT_SELF, string sScriptSuffix = "", string sWPTag1 = "", string sWPTag2 = "", string sWPTag3 = "", string sWPTag4 = "", string sWPTag5 = "", string sWPTag6 = "" );
void ClearCustomWaypoints( object oCreature=OBJECT_SELF, int bIsWalk = TRUE );
void StartWalking( object oCreature=OBJECT_SELF );

//  Initialize the custom WWP Controller.
object InitCustomWWPController( object oCreature=OBJECT_SELF, string sScriptSuffix = "" )
{
    SetWalkCondition( NW_WALK_FLAG_INITIALIZED, TRUE, oCreature );
  string sWWPTag = GetWPTag( oCreature );
  
  // Find the Waypoint Controller Object
  string sWWPControllerTag = WAYPOINT_CONTROLLER_PREFIX + sWWPTag;
  object oWWPC = GetWaypointByTag( sWWPControllerTag );
  
  // Create it if it doesn't exist
  if ( !GetIsObjectValid( oWWPC ) ) {
    oWWPC = CreateObject( OBJECT_TYPE_WAYPOINT,
      RR_WAYPOINT_CONTROLLER, GetLocation( oCreature ), FALSE,
      sWWPControllerTag );
  }
  
  // Store the Waypoint Controller object (and associated tag) on the creature
  SetLocalObject( oCreature, VAR_WWP_CONTROLLER, oWWPC );
  SetLocalString( oCreature, VAR_WP_TAG, sWWPTag );
  
  // Initialize the total
  string sPrefix = GetWPPrefix();
  SetLocalInt( oWWPC, sPrefix + WW_NUM, 0 );
  
  // Store the script suffix
  SetLocalString( oCreature, VAR_WP_TAG, sScriptSuffix );
  
  return ( oWWPC );
}

/*  Add a walk waypoint for the creature oCreature to the waypoint
  controller with the tag sCustomTag. This routine can be
  called repeatedly to add successive custom walk waypoints.
*/
int AddCustomWaypoint( object oCreature, string sCustomTag )
{
  // Check for a valid tag
  if ( sCustomTag == "" )
    return FALSE;
  
  // Check for a valid WWP controller
  object oWPPC = GetWWPController( oCreature );
  if ( !GetIsObjectValid( oWPPC ) )
    return FALSE;
  
  // Check for a valid waypoint
  object oWaypoint = GetObjectByTag( sCustomTag );
  if ( !GetIsObjectValid( oWaypoint ) ) {
    return FALSE;
  } else if ( GetObjectType( oWaypoint ) != OBJECT_TYPE_WAYPOINT ) {
    return FALSE;
  }
  
  // Store the next waypoint
  int nCount = GetNumWaypoints( oCreature );
    string sPrefix = GetWPPrefix();
  SetLocalObject( oWPPC, sPrefix + IntToString( nCount + 1 ), oWaypoint );
  SetLocalInt( oWPPC, sPrefix + WW_NUM, nCount + 1 );
  
  return TRUE;
}

/*  Set up to six custom waypoints by making repeated calls
  to the AddCustomWaypoint routine. 
*/
int SetCustomWaypoints( object oCreature=OBJECT_SELF, string sScriptSuffix = "", string sWPTag1 = "", string sWPTag2 = "", string sWPTag3 = "", string sWPTag4 = "", string sWPTag5 = "", string sWPTag6 = "" )
{
  // Initialize the controller
  object oWWPC = InitCustomWWPController( oCreature, sScriptSuffix );
  if ( !GetIsObjectValid( oWWPC ) )
    return FALSE;
  
  // Set the custom waypoints
  if ( ( sWPTag1 != "" ) && !AddCustomWaypoint( oCreature, sWPTag1 ) )
    return FALSE;
  if ( ( sWPTag2 != "" ) && !AddCustomWaypoint( oCreature, sWPTag2 ) )
    return FALSE;
  if ( ( sWPTag3 != "" ) && !AddCustomWaypoint( oCreature, sWPTag3 ) )
    return FALSE;
  if ( ( sWPTag4 != "" ) && !AddCustomWaypoint( oCreature, sWPTag4 ) )
    return FALSE;
  if ( ( sWPTag5 != "" ) && !AddCustomWaypoint( oCreature, sWPTag5 ) )
    return FALSE;
  if ( ( sWPTag6 != "" ) && !AddCustomWaypoint( oCreature, sWPTag6 ) )
    return FALSE;
  return TRUE;
}

/*  This clears the custom walk waypoints by causing
  the walk waypoints to be reloaded from scratch.
*/
void ClearCustomWaypoints( object oCreature=OBJECT_SELF, int bIsWalk = TRUE )
{
  // Set the first waypoint on the WPPC to null
  object oWPPC = GetWWPController( oCreature );
  int nWP = GetNumWaypoints( oCreature );
  string sPrefix = GetWPPrefix();
  int i;
  for ( i = 1; i <= nWP; i++ ) {
    SetLocalObject( oWPPC, sPrefix + IntToString(i), OBJECT_INVALID );
  }
  
  // Clear the counters
  SetLocalInt( oWPPC, sPrefix + WW_NUM, -1 );
  SetLocalInt( oCreature, VAR_WP_NEXT, -1 );
  SetLocalInt( oCreature, VAR_WP_CURRENT, -1 );
  SetLocalInt( oCreature, VAR_WP_PREVIOUS, -1 );
  
  // Reload the walk waypoints
  LookUpWalkWayPoints( oWPPC );
  
  // Set the walk flag appropriately
  SetWalkCondition( NW_WALK_FLAG_CONSTANT, bIsWalk, oCreature );
}

//  Start the creature walking the custom waypoints.
void StartWalking( object oCreature=OBJECT_SELF )
{
  // Use appropriate skills, only once
  if( GetSpawnInCondition( NW_FLAG_STEALTH ) )
      SetActionMode( OBJECT_SELF, ACTION_MODE_STEALTH, TRUE );
  
  // Add the new action mode stuff
  if( GetSpawnInCondition( NW_FLAG_SEARCH ) )
      SetActionMode( OBJECT_SELF, ACTION_MODE_DETECT, TRUE );
  
  // Make sure the walk flag is set and pause is turned off
  SetWalkCondition( NW_WALK_FLAG_CONSTANT, TRUE, oCreature );
  SetWalkCondition( NW_WALK_FLAG_PAUSED, FALSE, oCreature );
  
  // Set the next walk waypoint to the closest custom waypoint
  SetLocalInt( oCreature, VAR_WP_NEXT, GetNearestWalkWayPoint( oCreature ) );
  
  // Force resume
  SetLocalInt( oCreature, VAR_FORCE_RESUME, TRUE );
}


#3
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
If you want to script custom events at each waypoint, make a script titled:

"wp_<tag of creature walking waypoints>"

so if the tag of the NPC was "c_human", the script would be named:

wp_c_human

Here is a link with more information:

http://nwn2.wikia.co...ipted_waypoints

#4
Spectre-

Spectre-
  • Members
  • 7 messages
I am having trouble getting Example 2 to work with my creatures in my module.
I pull a commoner from the NPC list and place him in my module. I create a set of 3 way points for the creature. I then create the script and name it wp_c_commoner. 

Example 1 works perfectly with the creature walking and pausing, but when I use exmaple 2, the NPC freezes in place, and will not move.

Can anyone help me with this? My commoner is using the default NW_c_default09 on spawn script, and I have not changted it. Why is my commoner not moving??

Modifié par Spectre-, 12 août 2012 - 04:07 .


#5
Spectre-

Spectre-
  • Members
  • 7 messages
I tried creating a new area to test if it was something in the area I was using, but the NPC still just stays in place, he will kneel down in that one spot over and over again, but he does not move to any of the waypoints. Can someone explain to me why this is not working?

#6
Spectre-

Spectre-
  • Members
  • 7 messages
Hi all. I created an entirely new module and ran example 2 and it still didnt work. The NPC walks to the first point and then continues squating but no longer walking. Please help me with this.

#7
kevL

kevL
  • Members
  • 4 052 messages
hi, first don't use ActionPlayAnimation,

use PlayCustomAnimation

( list of animations )

2nd, don't loop it. The loop might be getting in the way, of the heartbeat trying to tell it to keep walking,

#8
Spectre-

Spectre-
  • Members
  • 7 messages
Thanks for your suggestions, I commented out the animation code lines and the random walking worked.
It does appear that the problem is isolated to the looping animations. Thanks. Strange that this code is in the walkway template and contains this error.

#9
kevL

kevL
  • Members
  • 4 052 messages
a substantial amount of stuff is leftover from NwN1. Advancements were made but sowed confusion as some systems gradually made way to newer ones. The closer something is to yr.2006 the more suspect it is,

g'Luck

#10
rjshae

rjshae
  • Members
  • 4 477 messages
Based upon the organization of the 'nw_c2_default1' script, it seems at first that you can't mix the walk waypoints functionality with the ambient animation. The GetWalkCondition routine called by this script checks the status of the NW_WALK_FLAG_CONSTANT on the calling creature. Thus you need to be able to turn this flag on and off in order to choose between walking waypoints and performing animation.

You might think could turn off NW_WALK_FLAG_CONSTANT using a scripted waypoint script. However, this script is run from the GetNextWalkWayPoint routine of 'x0_i0_walkway', which is executed by MoveToNextWaypoint. The latter next calls DoWalkWayPointStandardActions, which turns the NW_WALK_FLAG_CONSTANT flag back on.

A work-around is to have the walk waypoint script turn off the NW_WALK_FLAG_CONSTANT flag after the MoveToNextWaypoint function is exited. For example:

include "x0_i0_walkway"

// Stop the calling character from walking the waypoints
void StayHere( object oWP )
{
 [color="#333333"]. . [/color]// Halt the walk waypoint process
 [color="#333333"]. . [/color]SetWalkCondition( NW_WALK_FLAG_PAUSED, TRUE );
 [color="#333333"]. . [/color]SetWalkCondition( NW_WALK_FLAG_CONSTANT, FALSE );
 [color="#333333"]. . [/color]SetLocalInt( OBJECT_SELF, VAR_FORCE_RESUME, FALSE );

 [color="#333333"]. . [/color]// Cancel queued up actions
 [color="#333333"]. . [/color]AssignCommand( OBJECT_SELF, ClearAllActions() );

 [color="#333333"]. . [/color]// Do other stuff such as change facing...
}

void main()
{
 [color="#333333"]. . [/color]// Check if busy
 [color="#333333"]. . [/color]if ( GetIsFighting( OBJECT_SELF ) || IsInConversation( OBJECT_SELF ) )
 [color="#333333"]. . . . [/color]return;

 [color="#333333"]. . [/color]int nCurrentWP = GetCurrentWaypoint();
 [color="#333333"]. . [/color]int nNumWP = GetNumWaypoints();
 [color="#333333"]. . [/color]if ( nCurrentWP == nNumWP ) {
 [color="#333333"]. . . . [/color]// Stop walking the waypoints: call with a delay to escape WWP routine
 [color="#333333"]. . . . [/color]object oWP = GetWaypointByNum( nCurrentWP );
 [color="#333333"]. . . . [/color]DelayCommand( 0.1f, AssignCommand( OBJECT_SELF, StayHere( oWP ) ) );
 [color="#333333"]. . [/color]}
}

There you have it. The character walks the waypoints until he reaches a certain point, then he switches to whatever ambient animation he has set up. You will still need to start the walk waypoint process up by some means, such as through a heartbeat or perception process that turns the NW_WALK_FLAG_CONSTANT flag back on and turns off pause.

Modifié par rjshae, 17 août 2013 - 09:27 .


#11
Dann-J

Dann-J
  • Members
  • 3 161 messages

In NWN the WalkWaypoint() function had a flag that allowed you to specify whether the creature walked or ran their walkwaypoints. The NWN2 version of the function has been changed so that the TRUE/FALSE flag does something entirely different.

 

Is there a way to have a creature run their walkwaypoints in NWN2, rather than walk them?



#12
andysks

andysks
  • Members
  • 1 642 messages

Is a good question, because I tried to make it by setting the movement of the creature to really fast. But it looks really weird like that :).



#13
rjshae

rjshae
  • Members
  • 4 477 messages

In x0_i0_walkway, the function DoWalkWayPointStandard Action calls ActionMoveToObject with the optional arguments set to their defaults. It wouldn't be too difficult to modify the script to check for a boolean variable that would cause TRUE to be passed as the second argument to ActionMoveToObject, making the target run instead of walk.



#14
Dann-J

Dann-J
  • Members
  • 3 161 messages

In x0_i0_walkway, the function DoWalkWayPointStandard Action calls ActionMoveToObject with the optional arguments set to their defaults. It wouldn't be too difficult to modify the script to check for a boolean variable that would cause TRUE to be passed as the second argument to ActionMoveToObject, making the target run instead of walk.

 

That sounds doable - although I imagine you'd have to recompile every script that uses that include file (making it a laborious task).



#15
rjshae

rjshae
  • Members
  • 4 477 messages

That sounds doable - although I imagine you'd have to recompile every script that uses that include file (making it a laborious task).

 

Yes. I don't recall it being particularly arduous.



#16
andysks

andysks
  • Members
  • 1 642 messages

Just a thought. I was browsing through the combat animations. There is one RUNFORWARD under battle animations. I wonder what would happen if the NPC has this animation in the same style as we make them play cards and so on, but also has a wp system. Again, don't even know if possible or how the engine would treat such a thing.



#17
kevL

kevL
  • Members
  • 4 052 messages
well, an animation of any sort will cancel the previous animation, which will never come back unless the game makes an automatic call (eg. attack, idle etc.)


edit: or ofc if an explicit call is made, like scripted wps or HB.