You are on page 1of 76

Chapter One: The NWN x2_am ambient system (version 1.

55)
A tutorial by Ayath The Loafer greatly assisted by Nereng
August 2004 / May 2005
Ambient city by Nereng slightly assisted by Ayath
Appendix about waypoints by Baron of Gateford (updated May 27th)
(Thank you for allowing us to include it in X2 Ambient City)

This is NOT the end all and be all documentation for the ambient system. It is a sort of
walkthrough and also a tutorial where some points are explained and highlighted.
(I know it is a long document, but you can probably skip large parts)
Thank you for input and help: Heung Wei Lo and Hanor.
Special thanks to Nereng, who has done a lot towards testing out ideas and presenting new ways to
use the ambient system as well as designing the Ambient City demo. It was also Nereng who first
took up the challenge of the Lamppost Job and sparked my interest in the X2 Ambient System.
And a thank you goes to Firefairy for bug-testing Ambient City.
Baron of Gateford has kindly agreed to let us include his excellent tutorial on Waypoints in this
document. I am sure this will enhance your scripting greatly.
Throughout this document I will assume that you create copies of the creatures rather than painting
them in the area and then change their scripts and tags. This is because you will be creating generic
creatures that you can paint in the area and THEN change appropriately. Of course this will have all
your NPCs look alike, but this is a tutorial for the ambient system not a tutorial for creature
creation.
For your convenience I have created a demo module with the basic system demonstrated. You have
to reset the starting point to see the different areas. Nereng has made Ambient City to
demonstrate his ideas. He has commented in the scripts and the objects descriptions to explain to
you how each of them work.
I cannot stress enough that Ambient City is a fantastic piece of work by Nereng. Largely due to his
efforts we have had great response from the community. Id like to thank you all for your feedback.
Nereng has written a beginners guide to Ambient Animations. Find it in this document.
Guide updated May 22nd 2005.
My hope is that this tutorial will help the beginners to understand scripting better and to encourage
them to reverse engineer other peoples code to see if it can be changed to fit their needs.
Some of the scripts and ideas presented in the demo modules may even give you great ideas for
your own creations. That would make me happy.
Also important is it to realize that there are other NPC Activity Scripting Systems to be used in
NWN.

The best one is done by Deva Bryson Winblood and can be found here (last version I have seen):
NPC Activities 5.7.a3 SOU Edition
It is much better than the NWN Ambient System but then this tutorial is as much a description of
the NWN Ambient System, as it is a way of explaining to novice scripters what is going on in
scripts.

Index
Chapter One: The NWN x2_am ambient system (version 1.54)................................................1
What is the x2_am_ ambient system? .................................................................................................................... 4
What jobs are there to be had? (as seen in the x2_am_inc file) ........................................................................... 5
Main scripts for the ambient system .......................................................................................................................... 6

The x2_am_inc ............................................................................................................................................................................................... 6


The x2_am_heart.............................................................................................................................................................................................. 6
While we are on the subject of Heartbeats:...................................................................................................................................................... 6
Then there are the Spawn-In scripts................................................................................................................................................................. 8
And the OnUserDefined scripts ........................................................................................................................................................................ 8
We mustnt forget the conditional scripts ........................................................................................................................................................ 9
Or even the ActionsTaken scripts ..................................................................................................................................................................... 9

We find all the x2_am_ scripts.............................................................................................................................. 10


Ambient furniture...................................................................................................................................................... 11

Anvil.................................................................................................................................................................................................................. 12
Bookcase ........................................................................................................................................................................................................... 13
Lamppost .......................................................................................................................................................................................................... 14
Chairs Mate!..................................................................................................................................................................................................... 16
Wipe the table please! ...................................................................................................................................................................................... 18

Playing Tag (kids having fun) ................................................................................................................................... 19

So what is a fix-it trigger?................................................................................................................................................................................ 21

Dog chasing chicken (they are having fun) .............................................................................................................. 22


The chicken creating dog (also having fun) ............................................................................................................. 23
The Wanderer (a hunter in disguise) ....................................................................................................................... 25
The stray dog (can be told to go away)..................................................................................................................... 27
The hunter and the prey (this garbage pile creates rats)........................................................................................ 28
Faithful companion (follow the leader) .................................................................................................................... 32
The guard (the Spanish inquisition) ......................................................................................................................... 33
The number 2 guard (the lazy one) .......................................................................................................................... 36
The Blacksmith .......................................................................................................................................................... 37
The town hub (The Gatherings) ............................................................................................................................... 38
The Waitress and the Patrons................................................................................................................................... 40
Now what? .................................................................................................................................................................. 47

Chapter Two: Lets make the changes for the better ...................................................................48
Spelling mistake in x2_am_inc.................................................................................................................................. 48
Change to the heartbeat script x2_am_heart ...................................................................................................... 48
And then there is The Waitress ................................................................................................................................ 50
Prices are different from Inn to Inn ......................................................................................................................... 56

Chapter Three: Final words from Ayath.......................................................................................58


This is it....................................................................................................................................................................... 58
Navigating in the x2 demo module using The Invisible Listener ........................................................................... 58
Check out Nerengs Ambient City........................................................................................................................ 58
I sincerely hope this has been of use to you.............................................................................................................. 59

Chapter Four: Nereng guides you through the Ambient City.....................................................60


Nerengs Ambient Animations Tutorial............................................................................................................... 60
Specifically about the possible uses of the function GoToRandomPersonAndInit .............................................. 66

Appendix ...........................................................................................................................................70
What do all the different types of waypoints listed in the toolkit do? ................................................................... 70

What is the x2_am_ ambient system?


Bioware has included a set of scripts into X2 that can be used for ambient behaviour. The main
script is an include script called x2_am_inc and it deals with NPCs as well as animals that can be
told to maintain different jobs.
The main use of this system seem to be city behaviour and in particular tavern patrons and the
waitress job. Other uses made by Bioware include a town blacksmith, children playing tag, dog
chasing a chicken, hunters and prey, city guards etc.
The ambient system was created for Waterdeep, but was never really implemented as Waterdeep
turned out to be only one area. You can find traces of the system in the area, but nothing really
useable. Certain phrases found in the scripts clearly show that the system was in development and
never really got finished.
Actual calls to debug should be removed at end
In the x2_am_inc script
// * Bookshelf gets '
read'

In the x2_am_sitme script for the chair


returns true if can afford the ale
In the conditional file for can afford wine
Barmaid spawn-in script
In the Patrons spawn-in script
Not to mention loads of debug lines, some requests for thorough testing and the fact that the
barmaid/waitress script bits seem very incomplete.

As this is an unfinished system with small flaws here and there,


I have chosen to feel free to make my own amendments and
changes to the system.
Dont expect my changes to be fantastic but merely a moderate scriptors effort at making a complex
system work slightly better.
While I make no claim to have covered all areas of this ambient system, I have compiled this
document to illustrate most of its main features. You will also find a demo module that shows you
what this document covers. I have decided to add a couple of my own twists as I always do in my
tutorials.
Lets get on with it.

What jobs are there to be had? (as seen in the x2_am_inc file)
We shall start at the beginning by having a look at the lines in x2_am_inc that lead me to compile
this document.

!"#

"#

- .
-

0
1 #20

$
%
&
$ () * + % &
- * / .
" * $'

'
'

"

+3
4

56
-

" +

7
"
-

4
.

**
4

9
/(
**

+ 5 ! ++
+ 5 +
;
< =!
>
! =
36!+=

?
@

56

A
0

*
8

)(

85

! = (

40.

/
/

. %(

As you can see there are several interesting jobs to be had. Almost everybody on the Forums and
The Vault have had dealings with one waitress-script or another, so it will not be my main
priority.
The jobs mentioned above are only the ones that Bioware has made in this skeleton of a system.
There are certainly others jobs we can do with the system and Nereng has devised a very interesting
way of enhancing the system to make everything much more interesting (chained requests).
Maybe this is a good place to say that this tutorial in no way tries to make or even flog yet another
ambient NPC system to complement the ones already found on the Forums and The Vault. Keep in
mind that it is an effort to explain what the x2_am system is and what we can do with it.

Main scripts for the ambient system


While there is no documentation for this system we can certainly have a look at all the x2_am
files and try to figure out what they do.
There are two main scripts that are used extensively.

The x2_am_inc
The x2_am_inc is an include script which contains all the functions used by the ambient system.
It is in this script we find functions like SetJob(), DoJob(), Request() and a host of supporting
functions.
5
8$ () * + % '
5 +
"
$ () *
&
% 1*
!
BB&
1*
#
=C +. !
(
'
($ () * !"#
=#+ 0=1<'
" 8 0
$ () *
=#+ 0=1<'
5
(
8$ () * 0 /
=#+ 0=1<'
0
(
8$ (+
& () * 0 /
=#+ 0=1<'
5
+
$ () * 0 /
=#+ 0=1<'
0
+
$ (+
& () * 0 /
=#+ 0=1<'
" 8
(
$'
(
"
$ () * 0 /
'
0
($
(& () *
() *
=#+ 0=1<&
+
+
< 10=&
5
($ () *
() *
=#+ 0=1<'
($ () * 0 /
=#+ 0=1<'
*
1
$
D
& () * + %
=#+ 0=1<'
*
1
$
D
& () * + %
=#+ 0=1<'
5 1
$ () * + %
=#+ 0=1<'
#
$'
< * $ () * !"#& () * + < * '
"
+1
$ () * <
'
#
D
< 3 (6 $ () * #
'
! " 8
$'

/ BB'

Interested? Well get back to most of them.

The x2_am_heart
The x2_am_heart which is the heartbeat script used to fire the events when needed. We find the
request to DoJob() in this script among other nifty little details among which is the very useful
Day/Night posting.

While we are on the subject of Heartbeats:


There are many versions of the same warning out there on the Forums.
Dont use heartbeats. They will seriously slow down your module

While the above is true in huge modules with large numbers of creatures and events running all the
time (this is particularly true for persistent worlds), it is not necessarily true for modules of the six
hour play time or less type.
Certain procedures can be applied to minimize the problem and one of them is to make sure the
heartbeat doesnt do very much when theres no PC around to see things actually happen. To
prevent this Bioware has already implemented two of the possible ways of doing this in the ambient
system:
In the x2_am_heart we find this piece of code:
/$5

$'E

1=D=1 1

'

In other words
5

1
5

$'
. *

1
.
. *
/. /
%
1=D=1 !D 1 &
1=D=1 D= F 1
&
1=D=1 3 53&
1=D=1 D= F 3 53
5
1
$ () * + %
=#+ 0=1<'

1=D=1 1

&

1=D=1 !

1&

The Lexicon tells us that


0
0

1
$'
.
% . / *

/ *
.

4 8
/

&. %
(

. (

&(

(8

This suggests that creatures stop doing anything when PCs are not around.
To be absolutely sure of this there is another method that is also used in the ambient scripts:
! " 8

$'

G
() *
/$5

"# 5 !
#
() * D
$ "#'
< 10=
+ 6=
,
- 8

$# = +6 = +F"= "1 F=
+ 6='

#3

&"1 F=

#3

0 "#'

This is a function found in x2_am_inc that returns true if there are no PCs in the area.
This should be sufficient to keep the discussion on Heartbeat scripts to a minimum. If you are
programming a persistent world you have probably already achieved a scripting level superior to
this anyway and you have no need for this tutorial or solutions for heart trouble B-)

Then there are the Spawn-In scripts


Mostly the Spawn-In scripts are used to assign a specific job to an object or creature. Also this is the
place to assign the Day/Night settings, amount of gold carried, special SpawnInConditions etc.
A typical Spawn-In script could look something like this:
I *
I *

BJ7
B

*B
%

*B

$'
G
0 0#
5 5
+#
0
($
" +

$!
<1 5 !
1 56= =D=!+'
$
=#+ 0=1<&
$ 'K '
!&
=#+ 0=1<&+ 6='

And the OnUserDefined scripts


In these scripts you will find special behaviour for some of the creatures and NPCs. This is where
OnConversation events are executed. An abbreviated example:
I *

BJ7

*B

$'
G
6
/
$6
G
() *
/$5
G

5 6
:'

H
H

# !D= 0 +

() *
5 1 0() * D
$ () * '
/
/.

( $'
!
$'
+ 6='

We mustnt forget the conditional scripts


Used for the conversations these conditional scripts are very useful and quite frankly indispensable:
I *

BJ7

%#

*B
$'

($

=#+ 0=1<'

+ 6=

Or even the ActionsTaken scripts


Of course these scripts are also used in conversations.
$'
G
() * +
5 "#0$'
/$5
() * D
$+
'
< 10='
G
+
5 !
#
$# = +6 = +F"= "= #="+
H
0 1*
$+
&B!
1!
!20<
=B& '
H

!&"= #="+

! 0==!'

We find all the x2_am_ scripts


Try opening the script edit and open existing file. Click in the radio button for All resources.
Enter, in the Resource Name the first letters in the ambient system: x2_am.

As you can see there is a lot of jobs and job functions. Those with _sp_ I have determined to be
OnSpawn scripts and likewise the _user_ are the OnUserDefined scripts.
We are now on the right path to utilize the ambient system from Waterdeep. We must, however,
keep in mind that the complete system never was implemented and that it hasnt been thoroughly
tested. We are in fact trying to use an unfinished system.
In the next sections we shall have a look at some of the more basic uses.

Ambient furniture
One of the many parts of the ambient system is the furniture. You notice its presence in the x2_am
scripts:
x2_am_anviluse
x2_am_bookread
x2_am_lampuse
x2_am_sit and
x2_am_sitme
For all of them it goes that they have to be NearestObject by the character that is supposed to use
them.
And the easy part of it is, that all you have to do to make them work is apply the scripts and paint
them in the area. They will attract attention all by themselves.

Anvil
So lets start with the anvil use script. The first job is to decide in which script slot the script
belongs.
,
I *

%
BJ7

*
*B

(8( *

$'
G
,0
/$
G
0 "
C
H

L M
L
'N 9;'

.)

< %$
=#+ 0=1<&+ 6='
$+ 02
2 !D 1&A4 & 4
;&

=#+ 0=1<'

If Random(100) is greater than 35 then send a request that a task to be done. In this case it says, I
am an anvil. Come closer to about 0.5 metre away.
The x2_am_inc script has a function for the Request() function and it says:
,6
/$$ +
G

(8 !D 1 () *
+ 02
2

% #
% #
% #
8#
8#

$#
$#
$#
$>4 &
$>4 &

!D 1'OO $5

&#
& *
& *
% #
% #

($ #

'

1 #20

+3''

$''
+ () * $ 0 /
&< 10=&/
+. #
*$0 /
''
$#
&#
*
$'''
$#
&0
+=
$'''

''

This means: If your job is a blacksmith, stop what you are doing; Attack me (bash me). After 6
seconds Ive had enough. Stop and lets be friends again.
Those 6 seconds before we are friends again, doesnt that make you think of Heartbeats?
Of course it does.
Lets put the x2_am_anviluse script in the Heartbeat slot of the anvil.
Edit copy an anvil and put x2_am_anviluse in the heartbeat script slot. We shall test it later, but
presume it works.

Bookcase
This one is the x2_am_bookread script. And as with the anvil we shall presume that it goes in the
Heartbeat slot. No, I must confess; I have tested it and I am sure it goes in the heartbeat slot.
Just edit copy a bookshelf and you are good to go. You might ask why it should be edit copy all the
time. Why not just paint a bookshelf somewhere and then put the appropriate scripts inside?
Because if you edit copy and put the scripts where they belong, you can always paint that bookshelf
anywhere you want it. AND it already has the correct scripts in the slots.
In other words; IT SAVES YOU TIME.
,
I *

. /%
BJ7

L
*B

$'
G
,0
/$
G
C
H

L M
L
'N 9;'

.)

$+ 02 1= 06 =

2&

0+ !#=

=#+ + 12& 4
;&

=#+ 0=1<'

The x2_am_inc has this to say about the bookcase:


,6

(8(
. /
/$$ +
+ 02 1= 06 = =
2'OO $5
"#$ #
'
< 10='OO $
< 10=''
G
/$5 1
$#
'E 1= 06 = +3 =033 1 '
G
% #
$#
&#
*
$''
% #
$#
& *
+ () * $ 0 /
&< 10=&/
+. #
''
/$5
( 80* $ #
&
1 +F !+=11 5=!#='N A'
G
% #
$#
& *
" 8
$!
+ ! < =< 5=+ =
H
,)

($ #

'

''

*. .

G
% #
*

" 8

$!
% #

$#
&
+ ! < =<
$#
& *

5=+ " 60= 0#


8<

+#3 3= ''
() * $
=#+ 0=1<''

H
% #
*

$#
$

& *
#
$; '& #

$=J *

0* - $B

8 B& #

'''

'

The NPC that gets attracted to the bookcase either has a read animation or a scratch head animation.
The clincher is ability (intelligence) score of 9 or less.
8 = scratches head.
9 = reads a document.

Lamppost
We stay in the tradition of heartbeat with this script; x2_am_lampuse in the OnheartBeat slot.
I *

BJ7

*B

$'
G
,
/$5 1 *
G
" 8
8#
0 1*
8#
0 1*

/ /
/(8 /
$
=#+ 0=1<&B!

1 +6 !0=1< <<B'

'

$!
+ ! "1 #= 1= = #+ D +='
$4
:&
0 " * (
$
=#+ 0=1<&< 10=''
$
=#+ 0=1<&
B!
1
!B& '
$4
>& * 0
*1%. %$5
$
=#+ 0=1<'''
$

=#+ 0=1<&B!

1 +6 !0=1< <<B&

'

H
,
/$5 1 *
$
G
C
$+ 02
H

=#+ 0=1<&
B!
2 1

!B'

"" 0+&A4 & 4


;&

,
- /
/
/$5 1 *
$
=#+ 0=1<&
B!
1
!B'
G
C
$+ 02
2 1 "" 0+&A4 & 4
;&
H

OO 5

! %. $'

+ 6='

=#+ 0=1<'

OO 5

8$'

+ 6='

=#+ 0=1<'

Not much to say about this script. Lamp is off at creation, recomputes static lighting and waits until
night. Then it calls to someone and have them come closer. Please turn me on, it whispers.
x2_am_inc has this to say:
,6
(81 -"
() *
/$$ +
+ 02
2 1 "" 0+'OO $5
"#$ #
'
< 10=' OO $5
($ #
'P
+ 5 +'OO $5
($ #
'P
+ 5 ! + +''
G
( %$BP
P
1 - + % B& #
'
% #
$#
&#
*
$''
% #
$#
& *
+ () * $ 0 /
&< 10=&/
+. #
''
% #
$#
& *
* () * $ 0 /
''
% #
$#
& *
#
$=J * 0* - $B
7
8 B& #
'''
H

Someone cannot be a PC and cannot be from a tag team. The scripts assign a command
(ActionInteractObject) to someone who just happens to be closest. Then the someone gets told to
resume waypoint walking.
Bet you that this someone could be a guard on patrol with all his waypoints passing the lampposts.

You cant use the GUARDS from x2_am ambient system for this. Apparently there are some issues
with ambient animations and the WalkWaypoints() function. The guards never resume walking the
waypoints. Or so we are let to presume.
This is what it says in the NWN Lexicon:
2

+.
L
0 00 0-

.
#
#
/
%

$!
$!
/

(
.

8<1 5
<1 5
. *.
*
%
% .

/8

/ %
1=
=!+ !
-

*.
*
=!+ !
+ !0'4
%
8"

.
$' *

.
+

.
!0'

. %

4F

* L

OBSERVE: According to my associate in this tutorial venture, Nereng, there is absolutely no


problem with the guard and resuming WalkWayPoint after turning light on/off.
Back to the script. It turns out that the guard and lights out doesnt work.
The waypoint walking guard DO get called to the lamppost. He DOESNT turn the light on. He
DOES resume waypoint walking.
We must have a look at the problem why the guard DOESNT turn the light on.
Ah, we can see in the script that a certain variable NW_L_AMION is used. If we go look for it
through the scripts, we find another interesting script, which we should know about:
nw_02_onoff
about which is says, Turns the placeable object's animation on/off.
nw_02_onoff is put in the OnUsed slot of any placeable that has an on/off setting. By using the
object or by having an NPC interact with it, we can turn the lights on or off.
ALSO THE LAMPPOST NEEDS TO BE USEABLE.

Chairs Mate!
Did you hear about the Irish wake for Murphy? A lot of people attended and the room where
Murphy was laid out became rather crowded.
Wife and brother decided that they could sit Murphy on a chair in a corner instead of using all that
space where the dining table was.
The brother was holding on to Murphy while the wife and her brother packed the dining table away.
It was one of those tables where the legs could be folded back on themselves to make the table fold
up to less than a fifth of the original size.
As it turned out, Murphy was not that easy to hold on to. The stiffness had gone and his head was
lolling, arms were dangling, and he was actually starting to slip. The brother holding up Murphy
was getting a bit concerned and called out, Come on now, give me a chair for Murphy. From the
back of the room a slurry voice called back, Hip, Hip, Hoooraaayy.
Where were we? Oh yes, the chair script. Or should I say chair scripts. There are two scripts for
sitting that comes with the x2 ambient system. One is very short and sweet - x2_am_sit:
,* *

$'
G
() * 0 /
% #

=#+ 0=1<
$5 1 6

8$'& *

0 $0 /
''

And we can all see that it says click on me and GetLastUsedBy. We shall put this particular
script in the chairs OnUsed slot. Make the chair useable and you can sit in it.
The other script is same as anvil and lamp scripts. It requests an action to be taken and it is therefore
another Heartbeat script (according to the logic we have employed this far).
x2_am_sitme is the name of the script:
,
I *

. /%
BJ7

L
*B

$'
G
() *
/$5
*
/$5
G

5 0
%#
() * D
$0
'
1
"#$ 0

% #
() * 0 /
% #

$
=#+ 0=1<'
+ 6='G

$;& 0
'
'
< 10=OO 5 1
$0
&#
=#+ 0=1<
$0
& *

$0
$''
8<

'N
-

1= 06 = +3 =033 1 '
%

() * $ 0 /
&< 10=&

4 ''

H
H
,0
/$
G
C
H
H

L M
'N

L .)
7;'

$+ 02 1= 06 = 0 +&

0+ !#=

=#+ + 12& 4
;&

=#+ 0=1<'

Notice it says, Bookshelf gets read at the top of the script. Just proves yet again that the ambient
system is slightly rough around the edges.
Never mind.
If it works...
I have tried it in the inn with five patrons and four chairs, a bookcase and a waitress. The chair thing
looks ridiculous. Try for yourself.
Perhaps I would only keep the OnUsed script. Or perhaps I shall have to change something in the
ambient scripts somewhere.
And then there is the Table Wipe script.

Wipe the table please!


x2_am_tablewipe. If put on a tables Heartbeat slot we have the situation where the table calls out
for a task, namely Im dirty, come and wipe me. Or we could say that it would be the logical call.
Have a look at the script:
,+ (
I *
BJ7

(
*B

$'
G
,0
/$
G
C
H

L
L
'N >;'

$+ 02

.)

2 #1= ! !5&

0+ !#=

=#+ + 12& 4 &

=#+ 0=1<'

The TASK_WORK_CLEANING can be found in the x2_am_inc script and looks like this:
,6
(8+ 1= () *
/$$ +
+ 02
2
G
% #
$#
% #
$#
% #
$#
/*
+. . &94
;''
% #
$#
4
;''
H

#1= ! !5'OO $5
&#
& *
& *
& *

*
+
" 8

($ #

'

$''
() * $ 0 /
&< 10=&/
$!
+ ! 1
8<

''

+. #
''
" !5 5=+ 1

() * $ 0 /
&< 10=&/ *

&
+.

As you can see the animation is a LOOPING_GET_LOW.


What we can deduce from the script is that someone at Bioware has some peculiar drinking habits,
if he honestly thinks that a table in a bar should call for the waitress to CLEAN THE FLOOR in
front of the table.
If it were I, I would create a stain on the floor and then have IT call out for this particular cleaning
job. We must get back to this one.
The waitress can clean the table using LOOPING_GET_MIDDLE for a more authentic look
cleaning the table.
Or maybe its just me. Ah well.

Playing Tag (kids having fun)


Why not start in the city itself. We have all seen the children playing Tag and this system makes
it easy to implement and it will show the basis for some of the rest of the jobs.
We can figure out that the OnUserDefined script must be x2_am_user_play. If you doubt me,
have a look at the script.
Create your favourite little city exterior and edit-copy a boy and a girl. The two lovely little
creatures have a common Heartbeat and a common UserDefined script.
OnHeartbeat for both children is a script called x2_am_heart and the OnUserdefined is called
x2_am_user_play. Depending on who you initially want chasing who you can then attach a script
in the OnSpawn slot called x2_am_sp_it or x2_am_sp_notit.
For reasons you will see later I suggest you save some of the scripts under new names.
x2_am_sp_it is saved as x2_am_sp_cit.
x2_am_sp_notit is saved as x2_am_sp_cnotit.
x2_am_user_play is saved as x2_am_user_cplay.
Oh! You want to know why? Short and sweet: If you look at the scripts you will find that the
_sp_it file is also used for the chicken chasing dog and that the job WANDER is found in the
spawn script for the rat x2_am_sp_rat. And I want a wandering dog NOT with a rat-script. As
mentioned, the system is rough around the edges and I feel that it will be easier to explain and use
in the demo module if some of the scripts are saved under new names. We might also want to
change something in the relevant scripts (Actually I know we will).
There is no reason to make changes to the heartbeat script. Not yet anyway.
Lets get on with it then.
What will happen here is that these spawn script definitions starts the tag game going. Once the
game is in progress the child catching up will announce, You are it! and run away. The new IT
child will now give chase. This is done via some lines in the script x2_am_user_play (line 105
and on) where the job allotments are swapped.
This is according to the script x2_am_user_play. What happens in real life is that roles will never
be swapped. The reason for this I have located to the distance the IT has to be from the NOTIT to
enable the swap. It is written like this in the script:
/$5

*+

() * $ #.

'E

4 OO 5 1 *

$ #.

&BQ7 5 !=D= +B'

'

You must change the distance to something useful. In this case it will work if you change the
distance to something like 1.5 metres.
/$5

*+

() * $ #.

'E

4
; OO 5 1 *

$ #.

&BQ7 5 !=D= +B'

'

And why is this you might want to know? I have no idea.


While we are at it changing the x2_am_user_play script we might as well change the shout from
the IT child when the swap is made.
0-

%$B

P
B'

ut: Youre It!. Whats this? In my part of the world it would be something like DU ER DEN!
Or where my wife comes from: Tag! Youre It!
As you can see, there is ample reason already to make changes to the scripts.
Maybe you have noticed that there are some lines in the x2_am_sp_it file that says
- 8

/JM

%4

$.
.
%% '

8(

/.

*.

So what is a fix-it trigger?


We must investigate.
You will probably also have noticed the script file x2_am_exit_fixit. We know that fix-it is a
trigger and this is probably the exit script for that trigger. We make a sizeable trigger in the area and
spawn the kids into that and see what happens.
Also there are lines in the fix-it script that talks of a waypoint.
() *
/$5
G

#
() * D
% #

5 !
$#

() * $
=#+ +F"=
'
+ 6='

$ =J & *

() * $ #

F"

!+'

''

It doesnt seem to look for a specific waypoint and presumably it can be any waypoint. Paint one
inside the triggers area.
Thats it really.
And it works just fine. As soon as one from a tag-team has left the triggers area it is redirected back
to the nearest waypoint in the triggers area. We can then divide the towns area into segments for
tag-teams and of course use the trigger to keep the kids out of trouble like getting stuck in corners
and by stairs.

Dog chasing chicken (they are having fun)


This is basically the same as for the children playing Tag.
Again you can just use the exact same scripts in the exact same way only on a dog and a chicken.
And again I suggest you save some of the files under new names although in this case you dont
really have to, as the default scripts are just fine. I will save them under new names. I might hazard
some changes later on and in testing I like to keep things separate.
x2_am_user_play is saved as x2_am_user_dplay.
x2_am_sp_it is saved as x2_am_sp_dit.
x2_am_sp_notit is saved as x2_am_sp_dnotit.
Heartbeat stays the same (x2_am_heart).
It doesnt really make sense to have the chicken chase the dog, although it could make things
amusing. Should you decide to have this dog/chicken tag-team you dont want IT shouting, Youre
it! Of course this wont happen because there are lines to take care of testing if the IT and NOTIT
are player characters rather than dumb creatures.
() *
/$5
R

#.
5 !
() * D
$ #.

#
'

$# = +6 = +F"= "1 F=
+ 6='

#3

&
"1 F=

#3

! + "#'

If you dont want to have the chicken chase the dog, you will want to enter variables for the
chicken blueprint and set an integer X2_G_NEVERIT to the value of 1. This will be tested for in
the x2_am_user_play script and no exchange of roles in the game will take place.
1

/$5

*+

() * $ #.

'E

4 OO 5 1 *

$ #.

&BQ7 5 !=D= +B'

'

As with the children: You can use the fix-it trigger to keep them confined to a specific segment in
an area.
Hanor has drawn my attention to the fact, that the chicken sometimes would get stuck in corners, by
buildings and other obstacles. His solution to this problem is:
3
S4
4
4
/
*. (

(8*. % % *
4
. *. *

L.

8<
() * $ &+ 6=&
* *.
&
4
T

4 '/

(line 74 in x2_am_user_play)
Remember to save under a new name unless you want this change to be default.

;4 & %

The chicken creating dog (also having fun)


One thing you will notice if you go look for the x2_am scripts is a specific OnSpawn script called
x2_am_sp_dogchik which has this job-description:
0

($

+ 5

+&

=#+ 0=1<&< 10=&B

*. *

B'

According to the script it makes the dog create chicken that it then chases.
The x2_am_inc script has this to say about the SetJob function:
0

($

(& () *

() *

=#+ 0=1<&

< 10=&

/ BB'

So the dog gets the job as a tag-team member with the specific role as IT. It is NOT a
TownTalker and there is a string with ResRef townchicken.
Further down in the script x2_am_inc we find
/$
G

/P BB'

/ $
E
$9'K 7 KK'
G
() * #
#
() * $
=#+ +F"= # = +6 =&
0 1*
$#
&BQ7 5 !=D= +B&+ 6='
0
($
+ 5 ! + +& #
'
H

/
&5 1 *

=#+ 0=1<''

This leads us to believe that the dog when spawned should create two or more creatures with the
ResRef townchicken and with the local integer X2_G_NEVERIT set to 1 (or TRUE).
Just use the other default scripts for the tag team member IT (x2_am_user_play and
x2_am_heart in case you have forgotten).
You will want to save x2_am_inc under a new name, as we shall make changes to it.
Perhaps we shall look later at all the relevant changes and see if they collide in any way. If
they do not, we can combine the changes in fewer scripts.
Go create a chicken copy (remember the correct ResRef). Ill bet you twenty to one that the
townchicken has got to have the scripts mentioned for the NOTIT tag-team member (you can use
the default script for the chicken).
Lets check it out.

We have now established that the dog indeed creates chicken. My dog created two chickens. And
then it just stood there doing nothing. All the Tag-team scripts are in place, the ResRef is correct.
So what is wrong?
When I had two Tag-teams in one area nothing happened. One on one seems to work. My guess is
that it might be the number of chickens. Perhaps it gets confused?
Lets try that theory.
The above script lines mention Random(3) and this is a strong hint that some chickens will be
created. And this is indeed the case. I have had number from 2 to four chickens appear.

/ $

$9'K 7 KK'

Basically this means that the loop will cycle through values for i from 1 to random(3) +2
Random(3) means three values and we start at 0. (Thank you for pointing that out Heung Wei Lo).
You will therefore have a minimum of 2 chickens created and a maximum of 4.
Since we are testing if the non-chase problem has to do with more than one chicken we will change
the line in the x2_am_inc to something like
/$
G

/P BB'

/ $
E
$9'K 7 KK'
G
() * #
#
() * $
=#+ +F"= # = +6 =&
0 1*
$#
&BQ7 5 !=D= +B&+ 6='
0
($
+ 5 ! + +& #
'
H

/
&5 1 *

=#+ 0=1<''

and remember to save it under a different name. I suggest x2_am_inc_dcc. Then you have to save
the dogs OnSpawn script and save it as x2_am_sp_dcc after you change the #include file
refernce to include the new file x2_am_inc_dcc.
Again: The reason why we save the inc file under a new name is, that it might be silly to change the
spawn number to only one, if the spawn of several creatures will be needed for other of the
available jobs.
And it works now with the dog creating one chicken and chasing it.

The Wanderer (a hunter in disguise)


No I am not referring to the good old RocknRoll track but merely to a script set that makes a
creature go walkabout very much like RandomWalk, except there is slightly more to it than that.
We start by edit copy a new dog with the appropriate scripts.
And among those scripts is the usual heartbeat script x2_am_heart.
When we search among the x2_am files for an appropriate spawn script we find that the file
x2_am_sp_dogstra says: Stray dog wanders around but the job description is
SetJob(JOB_HUNTER);. If we search on we find the file x2_am_sp_rat which has this
description: The rat will use the WANDER work routine. It also states that the job is indeed
WANDER. Next statement is intriguing. As well, if it perceives a hunter, it will flee back to its
'
home'
.
Now what? We must have a look at the WANDER job description in the x2_am_inc file.
For the hunter and the wanderer we find
/$ (
G
0% =
H
/$ (
G
0 1
0 1
H

36!+= '
$

=#+ 0=1<&=

$=D=!+

+3=36!+= ''

! = '
%$
"

() * &+ 6='
$ () * &B36!+= B&1 0+=!

36!+F 6'

Clearly we have a hunter and its prey. We also find


,
*
G

$
@

? *
/$5
G
H
/$5 #
G
#
*
H
(

($'

%'

36!+= '

*
*

(8

$'P

#+

D=+ "

!+'

$'
$'

So if the wanderer isnt moving towards any point it will be told to stop what its doing and wander
randomly.

When we look further we find x2_am_user_rat which is what makes the rat differ from the
wandering dog. Apparently the script is also used for the hunter as well as for the rat.
We were, however, making a wandering dog.
We can use the heartbeat script x2_am_heart and x2_am_sp_rat for the wandering dog. We use
the default OnUserDefined script. Will he just stand still? No of course not. He moves around all
right.
That should cover the wandering dog. There is another interesting dog to be had. He is the stray
dog. We can expect very different behaviour from him.

The stray dog (can be told to go away)


So what is so different for the stray dog? Well, first of all he is friendly. He is likely to move
towards you to see if you might have anything good for him.
If you tell him to Go away using the chat window AND he is within 2.5 metres from you, he will
whimper and think you are a meanie.
According to the script he is supposed to perceive you, move towards you and bark.
Mine does bark but he doesnt move towards me.
Must investigate this one.
I had to put in an extra line in the x2_am_user_stray script.
/
$6

7'

"= #= D=

G
() * 1 " *
5 1 " *
$'
/$5
() * D
$1 " *
'
+ 6='
G
/$5
8$
=#+ 0=1<'OO 5
"#$ 1 " *
OO 5 #
*
$
=#+ 0=1<'P #+ !
'
G
#
*
$'
*
+ () * $ 1 " *
'
" 8D * #. $D #= #3 +
++1=# F '
H
H

'
+ 6=
D=+ " !+

So you can change the script accordingly (if you wish) and save it under the same filename. Doesnt
override the original, it is merely preferred if it exists. Weve been over this before.
Well leave the stray dog for now.

The hunter and the prey (this garbage pile creates rats)
When we refer to hunter in the x2_am_inc script it is in reality a specialized dog and the prey is
a rat.
We will start with the dog and save the very special rat (which is spawned by a placeable object) for
later.
We can create a dog with the job HUNTER. Usual heartbeat script and we can use the stray dogs
OnSpawn script (we should use the stray dogs OnSpawn for reasons which will become clear).
Save the spawn script as x2_am_sp_hunter.
Using the stray dogs UserDefined script you save it as x2_am_user_huntr.
Paint the dog in the area.
We are now set with the hunter. He will call out every second that he is on the prowl.
And now we shall create the prey, the poor little rat.
The heartbeat script is the same again, x2_am_heart.
In the x2_am_user_rat we find an interesting piece of code:
() * 3
5 1 * () * $
=#+ 0=1<&BQ7 1 3 60=B'
/$5
() * D
$3
'
+ 6='
G
00
%$B
%B'
,
.

Does this mean that she lives in a house? Apparently she stores the X2_L_HOUSE variable at
spawn time. We shall have to look for a script in which this variable is stored.
What then happens is that we find a function designed to create a rat
,#
#

$*

(8

8L

5 (%

* - '

$'

G
() *
#
() * $
0 1*
$
=#+ 0=1<&BQ7
, .
. / . .
0 1 * () * $
&BQ7 1 3
() * 0 /
=#+ 0=1<
% #
$
& *
H

=#+ +F"= # = +6 =&B


1
+0
=B&5 1 *
*
60=B&
=#+ 0=1<'
8<

() * $ 0 /
''

B&5 1 *
$
=#+ 0=1<''
=#+ 0=1<&BQ7 1
+0
=B'K '

This function creates a rat with the ResRef townrat at location OBJECT_SELF. This object must
be a placeable I suspect, as it then sets the local int on the rat X_L_HOUSE, meaning this is
where the rat lives (the filth that created it).
We must find this function that calls the function CreateRat(). It is found in x2_am_makerat. And
it is interesting (I use that term a lot dont I?).
J7
# -8 %. $*'7

# -4

,
*
8

4
4

+.
/ * - '4
/
(*

36!+=
. % (% . *
(

8
.

,
#
#

I *

BJ7

*B

$'
G
!
/$ !
G
#
H

(
(

/
/

5 1*
'

+0

=B'

$'

/$
$
'N $$ !
(
/
G
00
%$B3
BK
+0
00
%$B
%
U B'
#
$'
H
0-

=#+ 0=1<&BQ7 1

%$B5

, ; '''
%$ !

8B&+ 12D 16 = 0 1=!+ + 12'

''

, .

8&

The script stores the number of rats made. It creates one rat.
The CreateRat() function increments the local int X2_L_RATSMADE everytime it is run.
#

$'

G
() *
#
() * $
0 1*
$
=#+ 0=1<&BQ7
, .
. / . .
0 1 * () * $
&BQ7 1 3
() * 0 /
=#+ 0=1<
% #
$
& *
H

=#+ +F"= # = +6 =&B


1
+0
=B&5 1 *
*
60=B&
=#+ 0=1<'
8<

() * $ 0 /
''

B&5 1 *
$
=#+ 0=1<''
=#+ 0=1<&BQ7 1
+0
=B'K '

At next Heartbeat the variable is incremented by one. Another rat is created.


There will only ever be a maximum of two rats created at any given time. And thats a fact.
But when does it get decremented? It must be decremented at some point since the rat creating
process otherwise will stop after the second rat is created.
This is where it gets sneaky. The relevant function is found in the rats UserDefined script
(x2_am_user_rat):
,
#
*
() *

.
$'
+ () * $ 3
&+ 6=& 4 '
0 /
=#+ 0=1<
*

,
8 *
//
/$5 #
( $
=#+ 0=1<'
+ 6='
% #
$3
&
8#
$> 4 &0 1 *
$3
&BQ7 1
+0
=B'M '''
*
#
$
8 () * $ 0 /
''

5 1*

$3

&BQ7 1

+0

=B&

,/
8
3
&.
.
*.
/$5
($ () * '
36!+= '
G
% #
$ () * &#
*
$''
% #
$ () * & *
+ () * $ 0 /
&+ 6=& 4
7''
H
0 #
( $< 10='
,*
%
*
&
H

Makes perfect sense doesnt it? The garbage pile calls out to the dog, Go away. This gives the rat
time to see the dog. As soon as the dog is seen the rat moves towards its house, decrements the
X2_L_RATSMADE variable by 1 and sets the rat non-commandable. Not only does this take
care of the rats that are rushing towards safe haven, but also the rats that didnt quite make it.
Another interesting point is the SpeakString(Go away.....) which is run at every heartbeat.
If we use the stray dog set of scripts, this will mean that if the dog has approached the garbage pile,
and is just standing there, the dog will be told to go away. A cunning use of the listening patterns I
think. This will allow the rat to exist more than a few seconds giving it time to perceive the dog.
At least this is how I interpret the scripts until I see what actually happens.
The rat created uses the townrat set of scripts. We must edit copy a townrat with the correct ResRef.
Go do that. There is the usual heartbeat script and specialized x2_am_sp_rat and
x2_am_user_rat.

Depending on which rat blueprint you choose to use for edit copying a rat it will be faction
commoner or hostile. The rats OnSpawn script looks for an enemy:
/$5

($

() * '

36!+= VV5

8$

() * ''

We must therefore assume hostility between the rat and the dog. Since the dog is commoner (so it
doesnt attack us) the rat must be hostile.
Hostile rat blueprint is NW_RAT001.
And then we need to make a pile of garbage with x2_am_makerat in the heartbeat.
All there is left to do is run the module, find the area and observe. Nice isnt it?
But what if we want rats to be made in larger numbers? (That question was asked on The Forum).
In the x2_am_makerat script you could change the chances of extra rats being made to something
like:
/$

'N $$ !

'''

What about more rats made at every chance?


From the chicken creating dog we can steal this bit of code:
/ $
G
0
H

$9'K 7 KK'

. % . --

Say we want up to 4 rats created every time the makerat script allows for extra rats.
You could try wrapping the second CreateRat() in the above code

/ $
G
#
H

$9'K 7 KK'
$'

There are other ways, but these will do for this tutorial. Remember to save the script under a
different name if you dont wish the script change to influence all the creatures that use the original.
It is also a good idea to recompile the entire module once in a while if you constantly change
scripts. This is particularly valid if you make changes to an include script. ALL the scripts that use
this include script MUST be recompiled.

Faithful companion (follow the leader)


We also have a friend for someone when we investigate the x2_am_inc
*
G

>

() * <
5 1 * () * $
=#+ 0=1<&BQ7 1 < =! B'
/$5
() * D
$<
'
< 10='
G
() * #
5 !
#
$# = +6 = +F"= "1 F=
"1 F= #3
! + "#'
/$5
() * D
$#
'
+ 6='
G
0 1 * () * $
=#+ 0=1<&BQ7 1 < =! B& #
'
H
H
,/

#3

&

&/

G
/$5 #
*
$
=#+ 0=1<'P #+
G
#
*
$'
*
< *<
() * $ <
& 4
;'
H

! < 11

'

H
(
H

We can see that he attaches himself to any non-pc character that is a person.
In other words, we can have Old yellow or Lassie follow his master (Yes Lassie was a He, even
if He was called Good girl in the films).
You could try creating a commoner in an area. Put down a set of waypoint for him to walk and then
we create the faithful dog.
Notice that the dog does not have a Master initially and if oFriend is FALSE the dog look for the
nearest NPC and nominates him to be a friend. If it is a friend, follow him.
For the dog we have the usual heartbeat and the specialized OnSpawn script x2_am_sp_friend.
Thats it really.
And then there are the guards. There are two types of guards.

The guard (the Spanish inquisition)


There are two guards mentioned in the x2_am_inc script. GUARD1 and GUARD2. Lets look at
the OnSpawn script for GUARD1:

#
0< !
# -8 %. $*'7

# -4

,
-

* -

,
#
#
I *
I *

BJ7
B

*B
%

*B

$'
G
,%
L
0 1*
$
=#+ 0=1<&B!
0
($
56
'
8"
$'

1!

!20<

=B&

'

We notice right away that we are in fact looking at a Barmaid spawn-in script. It says so. Even
though the job is set to JOB_GUARD1. Well, its not really the barmaid spawn-in script. We only
see the result of a non-tested and not-finished system.
There is some connection with the Barmaid (or Waitress as some of us call her). The Guard has a
local int set to signify that he doesnt drink.
Lets create one of those guards and see what he does. Remember his waypoints or he shall just
stand there. You should use the usual x2_am heartbeat and his specialized OnSpawn script.
In the x2_am_inc we can read that guard1
56
-

7
"
-

4
.

**
4

So what does this GUARD1 actually do`


From the x2_am_inc file we can locate a function called GoToRandomPersonAndInit that is used
by both the waitress and the GUARD1 NPC.

In that function we can see that the GUARD1 will interact with people unless they are a GUARD2
or from a tag-team, have a master or is an animal.
/$5
($ !
'P
+ 5 + OO 5
($ !
'P
+ 5 ! ++
OO $5
() * D
$5
$!
''
< 10='OO
$5 1 *
$!
&1*
!
'P 1 *
#
=C
$5
8$ !
'
+ 6='
OO 5
* +8- $ !
'P
# 1 +F"= !
1
'

56

7 OO 5

+. !

( 'OO

($ !

'P

So what will he do? Well have a look at this:


#
*
$'
*
+ () * $ !
'
,0
. .$
/ (
.
, . 8%
'
0 1 * () * $
=#+ 0=1<&BQ7 1 1 0+"= 0 ! 0" 2=+ B& !
*
0
#
$!
'

'

He stops what he is doing (clear all actions), moves to the target creature and initiates a
conversation. On the way he sets a local int to make sure that he doesnt approach the same person
again (actually trying not to talk to same person straight away).
We seem to need a conversation file of some description.
If we give him a small conversation file we can surely test it to see if this is indeed the case.
We create a small conversation file with only a couple of nodes in it:

Of course it would be so much better if we had him come with a random conversation node. Also it
could relatively easy be made such that he only approaches PCs in a persistent world. Just to give
them a warning, You behave yourself or you will have to deal with me. Maybe even have a shifty
character approach the partys thief/thieves to warn, You pull anything here without a permit from
the guild...
The conversation is all this character does. Only thing is, that it doesnt work well with only one
character in the area. You need a number of NPCs as well.
Problem is he doesnt resume WalkWaypoint after conversation. Im sure I have seen somewhere
how to deal with this, but I cant seem to find it.

Nereng on the other hand had a solution right then and there. Cant believe I had forgotten about it.
What you do is NOT have the conversation end on the OWNERS node.
Nereng wrote this:
*
.
*

. $=!
+

.
. %
1 56='
. "#

* $'

G
*
H

$=J *

0* - $B

8 B&

=#+ 0=1<''

The number 2 guard (the lazy one)


The x2_am_inc has this to say about GUARD2:
56

A
0

85

40.

. %(

And that is absolutely correct. Thats what he does. You may wonder what he will be good for. You
may wonder what qualifies him for use in the ambient system. Perhaps as a bouncer at the Inn.
We use the ambient system heartbeat script x2_am_heart and x2_am_sp_guard2 in the
OnSpawn slot.
If we just check out his spawn in script we see that
0 1*

=#+ 0=1<&B!

1!

!20<

=B&

'

guards dont drink. The 10 is a number assigned to the variable to signal the waitress:
// * then set this variable for a short period of time
// * so that the person doesn't harass the same NPC over and over.
So this dude would be very useful in the tavern as he wont be approached by the waitress
when she goes looking for people to serve. Also he demonstrates what you have to do to stop
the waitress from harassing a character.
Thing is that there is another bit of code in the waitress part of x2_am_inc that says:
B!

8#
1!

$/
8
!20<
=B& '''

%<

& *

$0 1 *

$+

&

So in this code she sets the local int back to 0. Is this an indication that variables set on the NPC at
creation time are higher priority than those set through scripting? Does it override the Guards
reluctance to drink?
Maybe this command should be wrapped in an IF statement excluding the Guard from being reset.

The Blacksmith
This little fellow has got specialized scripts as well. In his Heartbeat we use x2_am_heart (no
surprise there) and in his OnSpawn we use x2_am_sp_blacksm.
His job description is JOB_BLACKSMITH and this is found in the x2_am_inc:
/$$ +
G

+ 02

% #
% #
% #
8#
8#

!D 1'OO $5

$#
$#
$#
$>4 &
$>4 &

&#
& *
& *
% #
% #

($ #

'

1 #20

+3''

$''
+ () * $ 0 /
&< 10=&/
+. #
*$0 /
''
$#
&#
*
$'''
$#
&0
+=
$'''

''

Not very much is it?


Well the lines above comes from the function Request() which is used by the ambient furniture to
request tasks being done to them. In this case it is the anvil signalling that it wants
TASK_WORK_ANVIL performed on it.
The blacksmith attacks the anvil and then they make up (SurenderToEnemies).
So we need an anvil to signal those requests, dont we?
The anvil has the following script on it:
OnHeartbeat: x2_am_anviluse
/$
G
0 "
C
H

'N 9;'

< %$
=#+ 0=1<&+ 6='
$+ 02
2 !D 1&A4 & 4
;&

=#+ 0=1<'

Thats it.
Signal request on a 35% chance: Please bash me.
You have a blacksmith with working anvil. Can it be improved? Yes!
Well on with that later. It is time we go on to the Town Hub.

The town hub (The Gatherings)


The city Hub is somewhere for people to go to. It is a placeable object that calls out for people to
come and join the fun. We are again talking Telepathy, as you wont actually hear the calls.
NPCs will feel an urge to gather around the hubs. The system is set up for four NPCs per Hub.
Each hub will call for more NPCs if there is less than four NPCs present at the hub.
The Hubs themselves are just any old placeable with special scripts and a special ResRef.
Edit copy your favourite placeable around which you want the users to gather.
ResRef = townhub
OnHeartbeat = x2_am_townhub
OnUserDefined = x2_am_user_thub
Thats it. Now you have a town hub.
Personally I think you should use an invisible object. And remember this: Because the Town Hub
has its own ResRef you can create them when needed.
Example: After a bell has sounded, a town hub is created, and people will start gathering around the
town crier and he can shout his important message.
But you need to get the right people for the hub. To be a hub user the NPC must have a special
UserDefined script: x2_am_user_townh as well as the usual heartbeat script. In fact you can use
the inn patrons we created earlier on. And you can have town hubs in the inn as well. Edit the
palette version of the patron by adding the userdefined script and paint new ones where needed.
In the x2_am_user_townh the NPC is moving towards the hub if certain conditions are met.
*

() * $ 3 (&< 10=&74
:'

Tells the NPC to walk to the hub and stop at a distance of 2.4 metres. So if you should want to have
a different distance, this is where to change it.
As soon as the hub goes active it will start to shout out for customers. Come hither. Should more
than four patrons turn up the surplus number will be encouraged to leave if another hub is shouting
out, I have need of more patrons. This can be found in the hubs UserDefined script where the
function AskPatronToLeave() is called.

That function looks like this:


,+

3 (
"

+1

$ () *

8&
<

. (

/ .

'

G
,
*. * .
. *
)
8
, 8 %
% . /
.
J
*
. (
() * ! " *
5 !
() * 8+ %$5 + %$
=#+ 0=1<''
/$5
() * D
$! " *'
+ 6='
G
0 1 * () * $ <
&BQ7 F36 B& ! " * '
% #
$<
& *
+ () * $ ! " * ''
() * "
.
5 !
#
$# = +6 = +F"= "1 F=
"1 F= #3
! + "#& ! " * '
/$5
() * D
$"
. '
+ 6='
G
,
.
/*
*. .
< *$<
&"
. '
H
H

#3

&

G
H
H

Personally I think that the type of animations played out by the patrons at the hubs should be reexamined. At least the percentage change for them playing should be adjusted.
Its up to you to decide what to do with the hubs. Well get back to some uses for the hub later in
this document.
There is an issue with the come hither coming over the DM channel making it irritating
with all those messages in the chat window.
Nereng has a solution:
"It's in line 69 (or thereabouts) in the
townhub heartbeat script: TALKVOLUME_SILENT_SHOUT. According to Lexicon this
uses the DM channel, so it can be heard across the entire module. I tried
exchanging it with TALKVOLUME_SILENT_TALK, and that fixes it. The only drawback
is that NPCs won't be able to hear townhubs across areas, but I don't think
that's a big issue.
"

Now it is time to get on with some important people. The Waitress and her Patrons.

The Waitress and the Patrons


If you edit copy any friendly NPC (perhaps the waitress) and put x2_am_heart in the heartbeat
and x2_am_sp_barmaid in the OnSpawn slot, you have created the basic waitress.
Try putting a few patrons in the inn room and she will approach them individually. Exactly like the
GUARD1 we made earlier on.
But basic isnt enough. We need conversation. We need drinks. We need more.
We try tracing trough x2_am_inc.
0

($

(& () *

() *

=#+ 0=1<&

< 10=&

/ BB'

G
0 1*
/$ (

() * &
BQ7 5
'0

B&
-

('
" * $'

So if the job is a waitress, we run to the function that sets up the prices:
,
0

- .
-

- * /
" * $'

G
0 #
0 #
0 #

+
+
+

$ :&
$ ;&
$ >&

+0
+0
+0

%$"1 + # 0+ 1=''
%$"1 + # 0+ 0"
+0''
%$"1 + # 0+
!=''

Smart isnt it? You set some variables at the start of x2_am_inc with the prices, and they will be
used in custom tokens.
Some of you may remember the 0.9b version of this document. I said some rubbish about the
variables being on the area. Thats not exactly true. (It would be smart because you could
have different prises at different inns/taverns/bars). For that we need to make changes to the
x2_am_inc script. Later in this document I will point out what to do.
The variables are integers because we can use them in arithmetic and they get translated into custom
token strings, because they can then be used in conversations.
We can test this theory with a small test conversation:

And it works.
Back to tracing the waitress bit in the x2_am_inc file.
In the SetJob function we also find:
, +.
*
(8
(
, /L
8
%L
.
, .
.
.
,8
L
L
0 1*
$5
$ () * '&5 + %$

() * '&

'

In other words, you must set a variable on the area to tell the ambient system, that this is the
waitress working area.
My waitress is for the moment just called WAITRESS1 and we now have the following variables
set on the area:

Kindly disregard the PLOT_COST lines, as they are clearly not working (see above read
text). They will be later on, so I leave them here as an appetizer.
The next bit is setting up the working zone:
,0
. L
W
L
&/ .
4+.
.
%%
, .
. !"#
() * + %%
5 !
() * $
=#+ +F"= + 55= '
() *
+ %%
5 <
"
() * $ + %% '
( + %%
< 10=
. $5
() * D
$ + %% '
+ 6='
G
/$ + %%
=#+ 0=1<'
( + %%
+ 6=
+ %%
5 ! J "
() * $ + %% '
H
/$( + %%
+ 6='
G
0 1 * () * $
=#+ 0=1<&B!
1 FX !=B& + %% '
H

As we can glean from the code, it must be the trigger into which the character spawns. As we saw
with the tag playing kids the trigger zone should have a waypoint that the character can return to if
it strays out of the zone. Remember the exit script in the trigger (x2_am_exit_fixit).
You might as well also put a tavern waypoint into the inn.

Next interesting bit that gives us another clue in this puzzle is this:

# -8 %. $*'7
,
!"#
( %
#
,

.
8(

#
#

# -4

/
(
- */
/
*

- 8
4

&

'

We stare at the line Can only be ran from conversation.


Also we can see some x2_am_act_ scripts that must be ActionsTaken from conversation lines.
By looking at them we should be able to set up a demo conversation by backtracking what the files
do.
This is definitely not one of my strong sides and before we continue with this exercise we should
create a couple of customers for the waitress to interact with.
Heartbeat = x2_am_heart and OnSpawn = x2_am_sp_patron.
First interesting action script for the conversation (if I am correct in my assumptions) is:
*
# -8 %. $*'7

# -4

,
/- 8

L
&
%. 4
!
*. * / .
(*
.
!"# . 8
L.
. 5 "#0$' 5 1 0-

.
() *
4

,
#
#

$'
G
() * +
5 "#0$'
/$5
() * D
$+
'
< 10='
G
+
5 !
#
$# = +6 = +F"= "= #="+
H
0 1*
$+
&B!
1!
!20<
=B& '
H

!&"= #="+

! 0==!'

Makes sense that we shall have a conversation node that says something like No thanks, I dont
drink.
So just to improvise the conversation, we now have

So if the waitress asks anyone (because we only have one node) they will tell her, that they dont
drink, and she wont bother them again.
(She uses SetLocalInt(oTalker, "NW_L_NODRINKSFORME", 10);).
Which for some reason isnt quite what happens. After a while she starts all over again with the
patrons. There is a timed delay

Lets examine the job description for the patron before we go any further (I have marked the
interesting places in yellow):
(

"

$ () *

0 /
'

G
() *
/$5
G
,

8#
() * D

3 (
8#

5 1 * () * $ 0 /
&BQ7
3 ('
+ 6='

. %& . 36

F36 B'

H
G
#

*
$'
#+
! =
#+ 1= D=
*
#+
! =
/$5 5
$0 /
'E :'
G
*
#+ 1= D=
H
/$ *
#+ 1= D='
G
() *
5 !
() * $
=#+ +F"=
'
/$5
() * D
$
'
+ 6='
G
,
. *
( 8
.8
.
8
0 1*
$0 /
&BQ7 5
60FB& '
*
81 * 5 1 *
$0 /
'
*
+ () * $
'
%
/ 5
/
$0 /
'
*
1* 5 1*
$
'
() *
( " * (
#
() * $
=#+ +F"= "1 #= 1=&B- *
()
B& 1 *'
% #
$
( " * ( & *
#
$
8#
$<" + ! =1 F&
*
#
$#
#
$
/
& 1 *& 81 *&
$ 'K '''''
% #
$
( " * ( &
8 () * $
( " * ( &<" + ! =1 F K
4 ''
*
#
$
8 () * $ 0 /
''
H
*
H
/$ *
G
() *
/$5
G
/$5
G
*
H
H
/$
G
" 8
H

#+

! =

#+

! = '

5 !
() * D
$
*+
+

*
H
H
H

() * 8+ %$B+
'
+ 6='

() * $
() * $

'N 74 '
'

'N 7;'
(

$'

G
H

$'

- *

(8

B'

object oMyConversationHub = GetLocalObject(oSelf, "X2_MYHUB"); must mean that the


patron uses the hub system. In this case the hub is inside and has changed name from TownHub to
ConversationHub. Never mind. We will remember this.
if (GetGold(oSelf) <= 4) tells us that the patron will leave the room if he has less than 5 gold
pieces left. We had better examine the prices we put on the drinks in this joint.
The patron will leave through object oDoor = GetNearestObject(OBJECT_TYPE_DOOR);
(actually he gets disintegrated or maybe beamed up) and the doorobject will recreate him after some
time with more gold to spend.
Should the Patron go wandering they will head for object oBar =
GetNearestObjectByTag("TOWN_BAR"); if it is more than 12 metres away.
You know what? We should really try to improve on the waitress conversation. We can find some
scripts clearly meant for this conversations Text appear when and Actions taken slots.
The Text appears when scripts have to do with the patrons ability to afford the different drinks.
Since the waitress will use the FIRST conversation node when she engages an NPC in conversation
we have to prioritise in a way that the patron is sold the most expensive drink first.
Conditional scripts available at the moment are x2_am_con_gpale and x2_am_con_gpwine.
These scripts test if the NPC has gold pieces enough to pay for these refreshments.
We can then start out with three conversation nodes:
Yes the patron can afford the wine Text Appears When - x2_am_con_gpwine
Yes the patron can afford the ale Text Appears When - x2_am_con_gpale
I dont drink this is default and always appears.
This conversation will then start with the line for the most expensive refreshment.
Likewise we need the patron to pay for the drink. This is done in the Actions taken for the
appropriate nodes.
Text Appears When - x2_am_con_gpwine
Would you like a glass of wine, Sir?
Here you are Sir
Actions Taken x2_am_act_paywin
Text Appears When - x2_am_con_gpale
Whatll it be? Ale?
Here you go!
Actions Taken x2_am_act_payale
This is default and always appears in PC conversation or if patron has run out of money.
I dont drink

With a better conversation.


With the ConversationHubs in place.
With a door for the patrons to leave by.
With a bar waypoint. With tables to wipe.
Its not that bad is it?

Now what?
If you have read this far and have had a look at the x2_am_ scripts you will no doubt have noticed
that there are some scripts I havent mentioned.
x2_am_con_atwork
x2_am_conv
x2_am_converser
x2_am_daynight and
x2_am_store
Why is that? you may well ask.
x2_am_con_atwork is clearly another conditional script for a conversation. It could be great to
have this condition on the first conversation branch so that the NPC can have a completely different
response set if she is going home from work (not at job).
For instance you can have the waitress say something like: Please leave me alone. Just because Im
a waitress doesnt mean I have to put up with this after hours.
x2_am_converser is empty. It only hints to the fact that it is meant for the Conversation Hub.
x2_am_daynight is quite frankly not a lot of good as it is now. Nereng has tested it thoroughly
and hes not happy with it. The NPCs simply vanish into thin air when its time to go to their night
lodgings. And they appear again at the position they left when it is day again.
The only creatures that this would suit are vampires, werewolves, ghosts and suchlike creatures. In
reverse of course. The day/night thingy.
x2_am_store simply opens the nearest store. Not much in that really.
x2_am_conv is another script to put in the OnConversation slot.
But this isnt over yet.

Chapter Two: Lets make the changes for the better


It is time to make practical use of the x2_am ambient system created by Bioware. It cannot,
however, be used with any great success unless some changes are made to it.
I have already pointed out some places where changes might be a good idea and we start of by
creating a new set of ambient scripts to reflect these changes.
After that I shall make further changes to the x2_am_inc script simply because I think things are
missing. Just think back at the waitress conversation and behaviour. Theres clearly room for
improvements.
Nereng has already put together an impressive number of uses for this system to create other NPCs
for the system than mere patrons, waitress and blacksmith. We shall attempt to create a set of scripts
that will enable you to undertake your own changes and create an entire city populated by NPCs
and small domestic creatures.
I shall document all the changes so that you can follow what were doing and learn how to do your
own stuff.
If you had read some of the communications between Nereng and myself you would have noticed
several lines of although Im not very good at scripting, Your capable hands, Clean up code
and various other bits of reassuring and confidence boosting lyrics.
None of us will claim to be great scripters and we are both autodidact.
We do however claim that the scripts we use in the demo modules are working fairly well. Or we
wouldnt have released them.
Please make a note of this: There are probably smarter ways of achieving what we do, but the way
we do it can be understood by scripters fairly new to the NWN Aurora Toolkit.

Spelling mistake in x2_am_inc


Nereng pointed out that there is a spelling mistake in the x2_am_inc script. It is in line 546 where
there is an E missing in NODRINKSFORME

Change to the heartbeat script x2_am_heart


I mentioned heartbeats earlier in this document. That you shouldnt be too concerned with heartbeat
scripting PROVIDED you made sure they didnt run unnecessarily.
I still mean that. After all, what do you think makes the game work? Constant monitoring of what
the player is doing and constant execution of code to cater for every little press on the w key or
whatever. This doesnt mean that we can go overboard with heartbeat scripting.

I mentioned that x2_am had two ways of dealing with not executing code when there was no PC
around to see anything happen.
In the x2_am_heart we find this piece of code:
/$5

$'E

1=D=1 1

'

In other words
5

1
5

$'
. *

1
.
. *
/. /
%
1=D=1 !D 1 &
1=D=1 D= F 1
&
1=D=1 3 53&
1=D=1 D= F 3 53
5
1
$ () * + %
=#+ 0=1<'

1=D=1 1

&

1=D=1 !

1&

The Lexicon tells us that


0
0

1
$'
.
% . / *

/ *
.

4 8
/

&. %
(

. (

&(

(8

This suggests that creatures stop doing anything when PCs are not around.
To be absolutely sure of this there is another method that is also used in the ambient scripts:
! " 8

$'

G
() *
/$5

"# 5 !
#
() * D
$ "#'
< 10=
+ 6=
,
- 8

$# = +6 = +F"= "1 F=
+ 6='

#3

&"1 F=

#3

0 "#'

This is a function found in x2_am_inc that returns true if there are no PCs in the area.
Personally I prefer the last version (NoPlayerInArea). Not because I dont trust the AI_LEVEL
thing to work, but because it is the game that decides when to shut down heartbeats.
You mustnt forget that the AI_LEVEL system allows you to create NPCs or events that DO run
even if PC isnt around. All you have to do is to use the function SetAILevel().
I gather this will be especially useful in a persistent world where certain events have to take place. I
wouldnt want to go deeper into this discussion. Sufficient to say that I shall make changes to the
heartbeat script so that you can choose witch version you want.
This is how the start of the main function in x2_am_heart looks now:

$'
G
,
0

( .
1=D=1
"# 1
$'E
1=D=1 1
VV! " 8
8
1=D=1
/$5
1
$'E
1=D=1 1
'
8
"# /$! " 8
$''

/$5

$''

The two || are the logical OR just as the two && is the logical AND.
You can then decide for your self if you want the one method, the other method or even if you want
both ways of minimizing CPU load.

And then there is The Waitress


As she is now in the bit we have done with her earlier on she is only approaching a patron. Checks
out his inventory to check how much gold he has and then she decides what drink to give him. She
doesnt need to go to the bar for refill or even to fetch the order.
To change this behaviour we check out the waitress job description. What we find is that the
x2_am_inc uses this in the DoJob() for the waitress:
*. $5

($''

G
,
*

.
5 +

"

$0 /
&
B!

1!

!20<

=B& ' (

So she goes to a random person and inits.


The function (GoToRandom.....) is used for the guard as well as the waitress as you can see from
the code. Some might ask if this means that the code could also be used by other NPCs. The
answer is a Yes it can.
All it really does (I use this sentence in loosest possible way) is to mark the last person spoken to
and then initiates a conversation set on the NPC calling the function. And as you might remember;
the conversation had branches that was depending on how much gold the patron had.
We need to improve on this scheme. So how do we go about it?
We need some way of directing the DoJob for the waitress in different directions according to four
options:
1)
2)
3)
4)

she isnt busy with a patron


she has received the order
she fetches the order at the bar
she is bringing the order back to the patron

5) she is ready for new patron


So how do we track when shes doing what? VARIABLES.
ORDER to tell us what drink she is fetching/bringing.
X2_L_LASTPERSONISPOKETO to tell us whom she has to go back to with the drink.
1) she isnt busy with a patron
ORDER = 0
X2_L_LASTPERSONISPOKETO = 0
2) she has received the order
ORDER = set to a number telling what drink is ordered
X2_L_LASTPERSONISPOKETO = Object(Patron)
3) she fetches the order at the bar
ORDER = set to a number telling what drink is ordered
X2_L_LASTPERSONISPOKETO = Object(Patron)
4) she is bringing the order back to the patron
ORDER = set to a number telling what drink is ordered
X2_L_LASTPERSONISPOKETO = Object(Patron)
5) she is ready for new patron
HASGOTCUSTOMER set back to 0
X2_L_LASTPERSONISPOKETO set back to 0
This is the rough outline.
First thing we do is we make a conditional if on the above switch. This would be somewhere near
line 284 in the x2_am_inc include script. Remember that include scripts are not automatically
recompiled. It is the scripts that include them, that need to be recompiled.
*. $5

($''

G
,

*
G
/
$5 1 *
G
5 +
H
(

$
"

=#+ 0=1<&
B

= B'

$0 /
&
B!

'
1!

!20<

=B& '

We must also change the Conversation file to fit the new situation. And we have to have each
conversation line happen in the correct sequence.
My new conversation file for the waitress looks like this:

As you can see I am also trying to use the Custom Tokens we made to contain the prices for this
particular inn.
AH! I never did that did I? Making it so that the prices could vary from Inn to Inn? Well get back
to that one. Promise.
Lets get back to the conversation.
Initial approach: How may I help you?
PC can answer any of the three, but the patrons answer is dependent on whether or not he has
enough gold to spend.
As soon as the patron has answered the waitress goes to the bar and tells the Bartender what the
patron ordered. Bartender answers and she then goes back to the patron with the order and gets
paid. She is then ready to pester a new patron.
There are Conditions on each branch and Actions Taken when needed.
From earlier on we remember that the conversation file works with a number of lines with
conditions on them (Text appears when) and a single line without condition.
So if no condition is met the conversation defaults to the last line/branch with no condition.
In this case the condition is found in the variable ORDER set on the waitress. If it is 1, we see
the line A glass of wine. And whom would she say this to? To the bartender of course.
Lets follow a typical day in the life of a waitress.
The waitress scans the room. Is there anyone who could need a drink? She finds a victim (customer)
and heads for him. IF THE VARAIBLE ORDER = 0. If it is she does the famous
GoToRandomPersonAndInit(oSelf,"NW_L_NODRINKSFORME",10);
The GoToRandom... function basically starts up the conversation with the random person.

In the conversation for the default line there are three possibilities. Two with conditions on them,
and one default.
The customers purse is quickly scanned and if he has enough money for wine he orders wine. If
there is only enough for ale, he orders ale and if he hasnt got any money he comes with a lame
excuse.
Lets pretend he has got enough money for wine. He then answers the waitress question with A
glass of wine please. At the very instant this sentence is uttered a script is run where the variable
ORDER is set to 1 and the waitress is sent to the bar waypoint and start her conversation file
$'
G
0 1*
*
*
0

$
+
#

=#+ 0=1<&
B
= B& '
() * $5 !
() * 8+ %$B+
!
$5 !
() * 8+ %$B!

B'&
< 10=& 4
;'
+=! = B'&
B

B'

again, this time with the bartender. Because of the other lines with conditions on them (and they test
for content in the variable ORDER she tells the bartender A glass of wine. which appears
because of a Text appears when condition like this:
0

%#

$'

G
-* *
/
$P
$5 1 *
$
< 10=

(
=#+ 0=1<&B

= B'

''

+ 6=
H

This one is made by the script wizard and is highly readable.


To be precise: The script was made by the script wizard and changed by me because the script
wizard always put in PCSpeaker as the object to store the variable on. And since this is used for
PC as well as NPCs AND they change during the course of the conversation file, I want the
variable to be on OBJECT_SELF, which is the owner of the script e.g., The Waitress.
Anyway. The bartender answers with Right away. A glass of the finest wine, and immediately the
variable ORDER is changed again and the waitress is sent on her way through the Actions
Taken script.
$'
G
0
.
0 1*
$
() * +
*
+
*
0
#
H

(
=#+ 0=1<&B
= B& '
5 1 * () * $
=#+ 0=1<&BQ7 1 1 0+"= 0 ! 0" 2=+ B'
() * $ +
&
< 10=& 4
;'
$+
&
B
B'

As you can see, she is sent to LAST PERSON I SPOKE TO which is a variable stored when she
first picks out the customer.
The variable ORDER is changed to 10 and as luck would have it, it corresponds with an
appropriate line in the conversation file for when the waitress speaks to the patron again with the
line Here you are <Sir/Madam>. The finest wine we have.
$'
G
0
.
0 1*

(
=#+ 0=1<&B

= B& '

We must remember to reset the ORDER variable to 0 or the waitress wont serve any more
patrons.
We can script something to set the variable to <> 0 if for any reason we want her to stop serving for
a period. And this is also what happens if the customer for some reason moves out of her working
zone (remember that one?).
So we have to make sure her variable ORDER is set to zero if that happens. Well get back to that
one.
We have another Actions Taken script for the customers answer Hmmm. Glad I didn'
t get the
House Wine then
We use the x2_am already made by Bioware: x2_am_act_paywin
I *

BJ7

*B

$'
G
$B!

" +

! 79B&"1 + # 0+

!='

The customer is relieved of gold equivalent to the price already stated in the x2_am_inc file.
Check out the relevant function in the file if you dont believe me.
And the problem with waitress stopping to serve if customer leaves working zone could be solved
by having the script that sends her back also reset the variable ORDER.

This is done in the x2_am_exit_fixit script. Here is a new version of that


$'
G
() * =J
5 =J
% () * $'
/$5
() * D
$ =J '
+ 6='
G
() * 0 /
=#+ 0=1<
/$5
($ =J 'N '
/$5
$0 /
'
5
$ =J ''
/$5 1 * () * $ =J &B!
1 FX !=B'
0 /
'
G
% #
$ =J &#
*
$''
/) (
.
=
.
*
/$5
($ =J '
'
G
0 1*
$ =J &
B
= B& '
H
% #
$ =J &
*
" 8
$!
+ ! < =< 5=+ " 60= 0# +#3 3= ''
() * #
5 !
() * $
=#+ +F"=
F" !+'
/$5
() * D
$#
'
+ 6='
G
% #
$ =J & *
+ () * $ #
''
H
H
H
H

And that concludes our walkthrough of the waitress behaviour. You can have a look at the scripts
for the Waitress if you open her conversation file and have a look at all the branches and all the
lines.
There are still some issues with the waitress. If she gets distracted she might forget about the ale she
was supposed to bring to the customer. Ive experienced waitresses like that and find it to be part of
natural behaviour for a waitress.
Of course you cant mention anything to Nereng without him fiddling with it B-)
He points out that the forgetfulness is due to a ClearAllAction in the DoJob() function. Makes
sense really. He also points out that a solution could be to alter the heartbeat script slightly.
/$5 1 *

=#+ 0=1<&
B

= B'P

OO 5 1 *

=#+ 0=1<&
B

= B'P 7'

($'

You should be able to work out how to do this. If not you will just have to check out Nerengs
Ambient City.
And now we return to the prices. We should be able to have separate prices in separate
establishments. I was told that a drink could cost vastly different sums if you find yourself in the
right place. Ive actually tried this when I was a sailor. A bar in the harbour area beer cost 25
Danish kroner. In a bar in the red light district (swear on my mothers grave I was only visiting my
aunt) beer cost 85 Danish kroner.

Prices are different from Inn to Inn


In the x2_am_inc script we find two places. First in lines 44-46
"1 + # 0+ 1=
"1 + # 0+ 0"
+0
"1 + # 0+
!=

and lines 481-487


,
0

- .
-

- * /
" * $'

G
0 #
0 #
0 #

+
+
+

$ :&
$ ;&
$ >&

+0
+0
+0

%$"1 + # 0+ 1=''
%$"1 + # 0+ 0"
+0''
%$"1 + # 0+
!=''

Since we have the possibility of storing local variables on object, module and area from creation
time, we might as well try to use it well.
Lets set some variables on the are (which is the Inn)

That should take of that. Now we need the programming to find them in the x2_am_inc script.
Best not to do anything to lines 44-46. We might forget to set the prices or we might prefer only to
set the prices for Inn where it is appropriate.
So we need to do something to lines 481-487
We need to make sure that the default prices are in place. Weve done that
We need to make sure that the correct variables are set on the area. Weve done that.
And then we need to change the SetUpPrices bit of the x2_am_inc.

Here is my bid for programming.


0

" * $'

G
5
.
() *
0
/$P
5
G
"1
H
/$P
5
G
"1
H
/$P
5
G
"1
H
0 #
0 #
0 #

.
5

. *
1*
+ # 0+
1*

&
B"1 + # 0+

1=

+ # 0+

+
+
+

5 1*

1=B'

+0

5 1*

&
B"1 + # 0+
!=

5 1*

$ :&
$ ;&
$ >&

+0
+0
+0

'

&
B"1 + # 0+

&
B"1 + # 0+ 0"

+ # 0+ 0"
1*

=#+ 0=1<'

+0B'

1=B'

'

&
B"1 + # 0+ 0"

!=B'

+0B'

'

&
B"1 + # 0+

!=B'

%$"1 + # 0+ 1=''
%$"1 + # 0+ 0"
+0''
%$"1 + # 0+
!=''

And then we have to recompile all scripts that use the include file x2_am_inc. Rebuild module.

Chapter Three: Final words from Ayath


This is it
This is the final version of the tutorial for the x2 ambient system.
There are other features of the system than what I have mentioned in this document, but as Ive said
before, Im not great a programming and this tutorial/document is only to reveal large parts of the
ambient system. Not explain every detail and every possible use for it.

Navigating in the x2 demo module using The Invisible Listener


I have stolen Nerengs Invisible Listener and left him to help you around in the areas.
All you have to do is speak the word testmode in the chat window and then the invisible listener
will follow you around. If you then speak the tag of an area you will be transported to the area of
your choice.
Here are the tags for the areas:

Check out Nerengs Ambient City


He has taken the ambient system and created very interesting things.
He has shown that you dont have to settle for a guard and a waitress. Why not have beggars, con
artists, evangelists, prostitutes, cooks, maids, farmers etc. all utilizing the possibilities of the
ambient system.
And he has done you a great service. He has written documentation in the scripts he uses

(Lucky for me. I almost gave up trying to keep up with his work. He just wouldnt stop. He kept on
and on with new ideas on how to use the ambient system).
He has written comments in the objects properties. He has explained it all. It is there for you to
learn from, to use and to expand on.

I sincerely hope this has been of use to you


All this was written for you the inexperienced and the curious in the hope that it would help you
to understand how to utilize resources already present and to show you that it sometimes pays you
to do a bit of reverse engineering.
Maybe I even managed to get you going in a totally new direction with ideas sparked from this
stuff.
If you have seen something in the OCs or other peoples modules, dont hesitate to look for how
they did it.
Have fun...
Good luck with your module...
Ayath The Loafer

Chapter Four: Nereng guides you through the Ambient City


Nerengs Ambient Animations Tutorial
Nerengs beginners guide to Ambient Animations. I hereby give Nereng the Talking Stick for the
last words in this tutorial:
AMBIENT ANIMATIONS TUTORIAL!!!
In the following I'
ll walk readers through the process of creating some typical ambient NPCs,
namely the "stay-at-home" and the "townwalker" NPCs, and also the use of the tag
NW_INTERACTIVE on placeable objects.
Let'
s begin by creating an NPC in his home:
Tell the wizard to create a new city interior area and make it tiny (2x2). To make things simple, we
use the "Home Lower1" from the "groups" section. (Paint Terrrain - groups - Home Lower1 2x2)
This nice, little home has a stove, a table with two chairs, a desk on which lies a book with the
Bioware logo, and a big comfortable chair next to a bookcase.
Now let'
s make an NPC to live here. For the purpose of this little walk-through I suggest using one
of the standard NPCs that you find in Paint Creatures - standard - human. "Commoner, male" will
do nicely. Put him midway between the dinner-table and the large chair. To give him a bit of
personality, give him a new name. It is also a good idea to make a unique tag for him at this point.
You do this by right-clicking on him and choosing "properties". This brings up his properties
"basic" tab, where you can also change the appearance, and assign or make a conversation for him.
Our next step is to give him the correct "Spawn In" condition. Right-click on him, choose
"properties" and then "scripts". This brings up the list of scripts that he uses in this or that event.
The one we are interested in is the one in the OnSpawn slot which has the name "nw_c2_default9".
Click the button next to it called "Edit". This opens the script, so that we can look at it, and make
the changes we want. BEFORE DOING ANYTHING MORE: CLICK THE BUTTON "SAVE
AS", AND GIVE IT A NEW NAME. That way we avoid making changes to the default Bioware
script, and create our own script which we can safely tamper with. NEVER make changes to the
default scripts unless you are an experienced scripter and know what you are doing.
Now, let'
s have a look at it. Notice how there'
s lots of writing in green? These are comments that
explain what can be done by "uncommenting" various lines in the script. We "uncomment" by
removing the // in front of a script-line. If you study these comments you will soon be able to make
several different OnSpawn scripts and give your NPCs a variety of behaviour-patterns. You can
make them say something whenever they see a PC, make them "cowardly", "stealthy" and many
other interesting behaviours.
We want our "stay-at-home" NPC to use "ambient animations". There are three kinds to choose
from:
1) IMMOBILE. We get this by uncommenting line 106 which goes like this:

SetSpawnInCondition( NW_FLAG_IMMOBILE _AMBIENT_ANIMATIONS);


2) MOBILE. We get this by uncommenting line 119 which goes like this:
SetSpawnInCondition( NW_FLAG_AMBIENT_ANIMATIONS);
3) IMMOBILE/MOBILE CLOSE RANGE. We get this by uncommenting line 106
SetSpawnInCondition( NW_FLAG_IMMOBILE_ AMBIENT_ANIMATIONS);
and line 166:
SetAnimationCondition( NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
The first option (IMMOBILE) will make an NPC play random animations while staying rooted to
the spot where he was spawned. This is useful for guards and others who should never move
anywhere.
The second option (MOBILE) will make an NPC play random animations and wander about freely.
We use this on "town-walkers" who may also enter areas with TAVERN_ and SHOP_ waypoints.
More of that later.
The third option (IMMOBILE/MOBILE CLOSE RANGE) is the one we want for our "stay-athomes". This will make them play random animations, and they can move about in their homes to
interact with some stuff that we will put in later. They will also interact with each other by playing
out some animations like "greeting" and "talking". So now you "uncomment" the lines mentioned in
3), and click the button near the top left corner called "compile". Put the new script in the OnSpawn
of the NPC.
The next step is to put down some waypoints. Click the "Paint Waypoints" button on the extreme
right in your toolset and find the "Generic Stop Waypoint". Place one of these in the vicinity of the
table, another near the comfortable, big chair, and a third near the desk. He will now occasionally
walk to one of these. We'
re beginning to get some varied action already! Finally, put down the
HOME waypoint wherever you please. It just needs to be in the area. This waypoint does three
things: It changes the animations played by the NPCs a little, if the NPC was spawned with mobile
animations it makes him leave his home during the day (though there'
s a snag to this which I shall
get back to later), and it makes him use the "x0_npc_homeconv" when he sees a PC. The
"x0_npc_homeconv"??? That'
s right, you don'
t have it. But you can make it yourself simply by
writing a one-liner conversation and giving it that name. What the NPC says when he sees a PC
entering his home is completely up! to you. "What are you doing in my home?", perhaps. If you
want a more complex conversation you can import it from Ambient City, where the "homeconversation" gives the NPCs several random one-liners to choose from. Export to your erf folder
and import to your module.
Now we need some placeables. There are two chairs around the dinner-table which are
unfortunately a little too close to the table for us to do anything with. However, in "Paint Placeables
- standard - miscellaneous interior" there is a chair that looks exactly right. Place it near the table,
and because it has the tag "Chair" the NPC will occassionally decide to go and sit in it for a while.
If you also want PCs to be able to sit in it you can make it useable and open it'
s properties/scripts
page, then scroll down the list of scripts in the OnUsed slot until you find "x2_plc_used_sit".
We can also make the NPCs sit on the static chairs that came with the area by using an invisible
chair. Find the Invisible Object in "Paint placeables - standard - miscellaneous". Place it in the big
chair near the bookcase and rotate it untill it faces the right direction. Now, change it'
s name and tag

to "Chair", right-click on it and "Edit Copy" so that you can use it in other places in your module.
Make it "static" (properties/basic page) if you don'
t want PCs to use it. Finally, right-click on it
again and choose "Adjust Location". Set the z-axis (number beside Z) to 0,00. This is so that the
NPC will face the same direction as the chair.
Time to make some NW_INTERACTIVE placeables!
NW_INTERACTIVE divides all placeables into three groups:
1) Placeables with open/close animations that have inventories.
2) Placeables with open/close animations that don'
t have inventories.
3) Placeables with activate/deactivate animations.
Common to them all is that they must have the tag "NW_INTERACTIVE" and they must not be
static. The first group must also be useable, otherwise it won'
t have an inventory, the other two need
only to not be "static", but can be useable if you wish. Right-clicking on the placeable and choosing
"properties" will open the "basic" tab where you can change these states. Group 2) also needs to
have the "will save" set to 1. This group is fairly small and you propably won'
t be using it much
since it consists mainly of trap-doors and secret wall-doors.
Let'
s start by putting a standard armoire to the right of the desk. We open it'
s properties, and
noticing that it already has an inventory, we give it the tag NW_INTERACTIVE. That'
s all we need
to do in order to make our NPCs occassionally walk over and open it (or close it as the case may
be). There is a small trick we can play on it, though: If you uncheck the "useable" box and set it'
s
will save to 1, it becomes a member of the second group! Our NPCs will still open and close it, but
players won'
t be able to do anything with it. The armoire won'
t even light up when they cursor over
it. Useful if you like to give the player something to wonder about!
Now you can place a trapdoor to the left of the stove. There are two different to choose from in
"Secret Objects", the topmost is the one best suited for this interior area. Opening it'
s properties we
find that it is already not "static", so we give it the tag (NW_INTERACTIVE) and set the will-save
to 1. Here, too, you can uncheck the "useable" slot so that only NPCs can interact with it. I don'
t
recommend leaving this trapdoor for players to find as they would propably be more aggravated
than amused at finding a "secret trapdoor" that does nothing.
Now we need some placeables from group three. This also consists of lighting placeables, and
luckily CEP placeables work fine with NW_INTERACTIVE, so there'
s several to choose from.
Find the crystal ball in "Trades& Academic&Farm" and place it on the little table next to the big
chair. Don'
t place it right in the middle of the table, though. It needs to be closer to the edge towards
the room so that NPCs can reach it. Open it'
s properties as before, give it the tag, and uncheck the
"static" box. When activated by an NPC it will now begin to rotate. Unfortunately, if you make it
"useable", nothing will happen if a PC uses it. Open it'
s scripts tab to find out why - there is no
script in the OnUsed slot! Do you remember what we did with the chair to make it possible for PCs
to sit in it? Let'
s try the same here: scrolling down the list of possible scripts in OnUsed we find
"x2_plc_used_act", and voila! The crystall ball works!
The room needs a little more light, so now we put a candelabra somewhere. I'
ll leave you to decide
where you want it yourself. As before, we open it'
s properties to give it the tag
"NW_INTERACTIVE" and make sure it isn'
t static. This too can be made useable for players, and

this time we find that it already has a script in OnUsed called "nw_02_onoff". Good thing, because
we'
re getting tired of all that scrolling down the lists.
And that should be all except... there'
s a fourth group of placeables, isn'
t there? What about all those
placeables that doesn'
t have any animations? Well, we can give these too the tag
NW_INTERACTIVE and uncheck "static". The NPCs will then go up to it and play the GET_MID
animation, but of course nothing further will happen. I'
ll leave it to your own imagination to think
of placeables to do this with, except for one: the invisible object that you find in
placeables/miscellaneous. Put it on the kitchen stove, give it the tag, and uncheck "static". This will
make your NPCs interact with something that normally can'
t be interacted with.
I should also mention NW_ALTAR, which is a tag you can put on things you want your NPCs to
worship. Normally that would be altars, of course, but you could also give that tag to an invisible
object in front of the king so that his people will show some proper respect. Just don'
t spawn him
with ambient animations, or he will start worshipping too, which looks silly.
Another thing that needs mentioning is that you must uncomment in the OnSpawn script line 141:
SetAnimationCondition( NW_ANIM_FLAG_IS_CIVILIZED);
if your NPC does not belong to one of the player or humanoid races (orcs and goblins are
humanoids, demons are not).
In case you'
re now thinking that NW_INTERACTIVE is great, here are some downsides:
Placeables don'
t play the sound they should. Eg: a fountain doesn'
t make a running water sound and
torches can'
t be heard.
Lighting objects light up, but don'
t change the area lighting. This can look very silly in a "torch-lit
only" area.
Tagging doors as NW_INTERACTIVE doesn'
t work.
There is no way to control how much or little an NPC will interact with NW_INTERACTIVE
placeables. You can wait around forever before they do it, or they can get completely stuck opening
and closing the same thing over and over again. I can tell you that they seem to prefer talking to
other NPCs and sitting in chairs over using an NW_INTERACTIVE, though.
Finally, Georg Zoeller has earlier mentioned in the Scripting Forum that NW_INTERACTIVE was
made by Floodgate for Shadows of Undrentide, and that it is not officially supported by Bioware.
(So don'
t complain to Bioware about it.)
End of walk-through for "stay-at-home" NPCs.
Now for some "townwalkers"!
We make these by making a new version of the default OnSpawn script nw_c2_default9, just like
we did with the "stay-at-homes", but this time we uncomment line 119 which goes:
SetSpawnInCondition( NW_FLAG_AMBIENT_ANIMATIONS);
Once again: RENAME THE SCRIPT FIRST! Then put it in the OnSpawn slot of your townwalkers
properties.
The NPC will now chat with fellow NPCs and wander randomly about, except... he isn'
t going to

wander very far. He needs to know where he is supposed to wander, and for that you must place
some Generic Stop Waypoints. Find them among the standard waypoints and put them in all places
that you think he should visit. The Stop waypoints can'
t be too far apart. In my experience 20
meters between is about right (One area tile is 10x10 meters).
You can of course give the NW_INTERACTIVE tag to outdoor placeables too. An example: Place
a barrel somewhere, change it'
s name to "Trashcan", remove the tresure-scripts from it and give it
the NW_INTERACTIVE tag. Another idea is to put invisible objects with the tag on top of terrain
features like fountains and wells. And if the NPCs get weary from all the walking about they can sit
on benches and other things with the tag "Chair".
The "townwalkers" will also enter areas that are adjacent to the one they were spawned in which
have TAVERN- or SHOP- waypoints. So if you have some of those in your city or village you'
ll
want to place these waypoints there. There is a nasty snag to this, however: they never come out
again. The reason for this is that the engine is saving CPU power by dropping the NPCs AI-level to
very low when there are no PCs in the same area as the NPC. This makes them "forget" to leave the
area they are in (unless there'
s a PC there). There are some ways around this, the easiest being to
write this line in the OnSpawn script (The one you'
ve already renamed, NOT the default Bioware
script!):
SetAILevel(OBJECT_SELF, AI_LEVEL_LOW);
This will force the engine to always treat the NPC as if there was a PC watching him. The problem
is that the NPC will now be a constant drain on the CPU, instead of only taxing it when there are
PCs around. So this is something you should do as little as possible, especially if you are building a
PW or very big single-player module.
If a townwalker starts his life in an area with the HOME-waypoint he will leave it during the day
and return to it at night. This too suffers from the snag I just mentioned: if there'
s no PC around,
nothing happens. The solution is the same: SetAILevel.
In addition to luring townwalkers to their areas, TAVERN and SHOP waypoints make NPCs play
other animations than they would otherwise. (There'
s lots of drinking and laughing going on in
taverns).
I have seen some posters express concern that NPCs could start walking through several areas to get
to TAVERN, SHOP or STOP waypoints far from their home. IMHO this does not happen.
How many "townwalkers" should you have? Bioware has said somewhere that a good rule-ofthumb is one NPC per
five tiles. This means that a 10x10 area should have about 20 NPCs in all. My own experience
confirms this, but you
should take into account whether there are large, open spaces (town squares, parks), in which case
some extra NPCs are in
order. It is also a good idea to have NPCs with different behaviours: maybe a couple of guards are
walking waypoints,
another is standing at his post, there'
s a couple of immobile merchants with day/night postings and
maybe there'
s agroup of NPCs who are standing together, with Immobile/Mobile Close Range

spawn-in scripts. Or, since you have


the x2 Ambient system: maybe some town-hubbers, tag-playing children, and Beggar-Tim!
End of walkthrough for "townwalkers".
Day/Night posted NPCs:
One type of NPC you may have noticed in modules you have downloaded is the merchant who is at
the outdoor marketplace during the day but goes home at night. You can make your own by placing
a POST_ waypoint and a NIGHT_ waypoint. If your merchant'
s tag is "merchant1" the tags of the
waypoints should be "POST_merchant1" and "NIGHT_merchant1". Here too you must make a
special OnSpawn script, and this time you "uncomment" line 95:
SetSpawnInCondition( NW_FLAG_DAY_NIGHT_POSTING);
Would you like the merchant to play animations while standing at his POST- or NIGHT- waypoint?
The only hassle-free method I know of is the one used by the merchant in Ambient City. He has the
script "n_am_heart" in his OnHeartbeat and was spawned with both
NW_FLAG_DAY_NIGHT_POSTING and
NW_FLAG_IMMOBILE _AMBIENT_ANIMATIONS.
You can import the script to your own module from Ambient City.
Can you guess what happens if there is no PC in his home when it is time to go to work? That'
s
right. I'
m sure you can guess the solution too! Are you wondering exactly how many NPCs you can
have with their AI-level set to low? Me too. I currently have 29 of them in my module which is at
31meg unzipped (growing very slowly). It is still running smoothly, but that'
s all I can say.
Before finishing I'
ll just mention what I think is the easiest way to place ordinary waypoints for
guards etc: Left-click on the NPC, then right click on the spot where you want his waypoint to be.
Create Waypoint. Right-click again where the next waypoint should be. Repeat as often as you like.
Happy building!

Specifically about the possible uses of the function


GoToRandomPersonAndInit
The purpose of this update is first and foremost to show how the function
GoToRandomPersonAndInit
can be used to make NPCs with ambient animations have conversations with each other. It is not
difficult to do this with NPCs without the spawn-in condition
NW_FLAG_AMBIENT_ANIMATIONS - a simple user-defined script with
ActionStartConversation should do the trick, but these guys are another matter. The ambient
heartbeat will usually clear any actions you put in their queue within seconds (6 seconds to be
precise!). I won'
t go into detail about how the scripts work here, but simply explain where to put
them, hopefully in a way that will enable builders with no scripting knowledge to get started writing
conversations for their NPCs right away. If you are interested in the technical side of it there are lots
of comments in the scripts.
I made these scripts for one type of NPC primarily: The type who is spawned in with
SetSpawninCondition(NW_FLAG_AMBIENT_ANIMATIONS);
I may come back with scripts tailored to immobile and mobile close range NPCs, but in the
meantime you can try using the userdef script for townhubbers on them. The standard script might
not work too badly either, but it hasn'
t been tested. And of course, if you are a scripter you will
figure out how to do it yourself.
Finally, how to do it:
The first step is to put the script "n_am_usr_npc" in Properties/Scripts/OnUserDefined of your
NPC. There is no need to worry about removing the standard Bioware script in this case, as it does
exactly nothing. This script slot was made for us to put scripts in.
If the NPC is one of the townhubbers, you just use the standard user-def script for them. The "Init
chat" event has been incorporated in the new version.
Now you put the spawn-script "n_am_sp_m_anims" in the OnSpawn script slot of the NPC. Here I
have "uncommented" NW_FLAG_AMBIENT_ANIMATIONS and
NW_ANIM_FLAG_CONSTANT and written SetAILevel(OBJECT_SELF, AI_LEVEL_LOW).
You can comment out what you wish, but the line with:
SetLocalInt(OBJECT_SELF, "SHOULD_BE_AMBIENT", 1) should be kept, as it will be checked
elsewhere.
The line with SetAILevel is a bit draining on the CPU, however, so you might want to "comment"
(//) that. This is the line that makes the NPCs bright enough to leave their homes in the morning,
though.
The next step is to consider which of three methods you want to use to signal your NPCs to start
chatting with each other. From the heartbeat of a placeable, from a trigger that a waypoint walking
NPC steps on, or as a user-defined heartbeat event.
In the city square of Ambient city is an example of the PLACEABLE-method: the Sundial. The
script in OnHeartbeat of it is called "n_am_hb_chatcon" and randomly tells random NPCs to start
conversing with random friends (lots of randomness there). You can either import the sundial as it

is to your own module or just put the script on a placeable of your own. And that'
s all you need! Off
you go to write some conversations! If you want to, you can of course import the conversations
from Ambient City, and use them as a template or as they are.
The TRIGGER-method is very similar to the sundial-method (sorry - placeable method!). All you
need is a guard who walks between some waypoints, and the trigger "ChatTrigger". Paint several of
them in the path of the waypoint-walking NPC. It has a script in OnEnter ("n_am_chat_trigge")
which randomly signals nearby NPCs to start chatting randomly with each other. You can either
import the trigger, or just the script. It will only be triggered by a NPC with the tag "GUARD2".
And that'
s all there is to it here as well! This method should appeal to builders who don'
t like
heartbeats.
The last method is the UserDefined HEARTBEAT EVENT method, which is used by Flora in The
Halfway Inn. You set that by "un-commenting"
SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); in the OnSpawn script
"n_am_sp_m_anims", or you can use Flora'
s script "n_am_sp_multi". A lot of different events has
been set in her script, which goes with the "emote-triggers". Comment in or out as you see fit in that
script. The conversation on Flora has a large number of TextAppearsWhen scripts which are tailormade for NPCs speaking to NPCs. I hope you also like the script for an NPC healing another with a
potion.
Note that only NPCs with a class in "commoner" will be told to start conversations with the two
first methods. This is to make it easier for the sundial and trigger to pick out NPCs who have the
scripts on them. If you want some fighter, paladin or other class NPC to participate: just give them a
class in "commoner" or use the Heartbeat Event method.
I have done my best to reduce CPU strain from these scripts, but it has to be noted that both the
function GoToRandomPersonAndInit itself, and the sundial and trigger cycles through the area to
find valid targets. I believe this could be fairly CPU-intensive, but you will have to find out how
much yourself. In Ambient City it seems to be OK. Also, reducing the frequency (% chance that
they will fire) in the scripts will reduce this type of strain. This will also make it take longer before
the conversations between the NPCs become repetitive. Open the heartbeat script on the placeable,
and the OnEnter script of the trigger to do this.
Writing the conversations: Start by taking a look at the conversations on the NPCs. They are
am_talkative (on Flora)
am_waitress
am_x2_man
am_x2_female
Note that when the NPCs are speaking to each other, the PC conversation-node can be used. Also,
when the tokens points to one of the NPCs in the conversation, it is always to the one taking the
place of the PC. As usual, you must avoid putting scripts in a final owner-node, because it won'
t be
executed there.
Since neither the conversation-wizard nor the script generator will make conditional scripts that
work in NPC to NPC conversations, I'
ve made some for you:

n_am_taw_npc
n_am_taw_33npc
n_am_taw_pc

Returns TRUE only if the talked to is a NPC


33% chance of returning TRUE if the talked to is a NPC.
Returns TRUE only if the talked to is a PC. (Hehe!)

n_am_taw_doorman
n_am_taw_augie

Returns TRUE for the specific tag if it'


s the first time he is talked to.
Returns TRUE if the intended target (stored as a local object)
has the correct tag and is not a PC. (This seems to work

better

than using GetNearestCreature.)


Returns TRUE if the nearest creature has the tag, and that is also
the intended chat target.
n_am_taw_wound2
Returns TRUE if the talked to is wounded AND was the intended chat
target AND the caller has a potion of Cure Light Wounds.
n_am_taw_naked
Returns TRUE only if the talked to is naked and is a PC.
n_am_taw_wounded
Returns TRUE only if the talked to is wounded and is a PC.
n_am_taw_weapond
Returns TRUE only if the talked to has weapon in hand and is a PC.

n_am_taw_waitress

Finally, you should put the script "n_am_walk_wp" in CurrentFile Normal and Aborted to make the
NPCs resume their ambient animations more quickly.
Changes in 1.53
1. Fixed a bug where the shopkeeper would stop and never get to his POST_waypoint if you talked
to him in the morning right after he had left his home, by giving him a conversation line for that
situation.
2. Increased the shopkeeper'
s spot and listen skills to 8 so that he can see PCs who has tried to steal
from his chest in stealth mode but without having at least 8 points in Move Silently.
3. Moved all the ambient placeables blueprints to Special/Custom2 to make them easier to find for
builders who use CEP.
Changes in 1.5
1. Three new methods for using the function GoToRandomPersonAndInit. (NPCs randomly starts
conversations with each other and PCs.) With this comes also a bunch of TextAppearsWhen scripts
to use in conversations between NPCs.
2. Two fixes to the ambient waitress. She no longer stops working, and doesn'
t sell ale to the
bartender and door-guard.
3. Four emote-triggers for NPCs.
4. The merchant now uses NW_FLAG_SLEEPING_AT_NIGHT.
5. NPC sitting in a chair, and staying seated.
6. Several new placeables: Area lightswitch, Restingbed with a little twist, Background-music
changer, sundial, and many more.
7. A quick explanation of the x2 death system.
8. A fix to PCs closing the gate during the day, thereby shutting everybody inside the city. Thanks
to Sir Elric for pointing out this problem.
9. A trigger now stops Inquisitive Guard walking too far away from the gate.
10.A chest that makes nearby NPCs go hostile if you open it, but not if you are stealthy.

11.Tweaks and fixes here and there. New and old books in the library has most of it, or look at the
comments page of the object and the comments in the scripts.
Final note: Please don'
t hesitate to tell us if you find bugs or have comments on how you think this
package can be improved. And dont forget to rate either!
nereng
-

-ooOoo--

Appendix
What do all the different types of waypoints listed in the toolkit do?
By Baron of Gateford
This information is split into six sections.
The first section details the normal waypoint system (walkwaypoints)
The second section details the waypoints that can be used in conjunction with ambient animations.
The third section details the waypoint specific to the Beholder.
The fourth section details the NW_GENERIC_MASTER variable which needs to be set on NPC'
s
for certain settings.
The fifth section details how to set thee AI level on NPC'
s to make them walk even if the PC is not
in the same area.
The sixth section details other guides/systems that you may find useful
WAYPOINTS USED WITH WALKWAYPOINTS (or normal waypoints)
There are 4 different types of waypoint to get your NPC to move around in a set pattern via
the standard Bioware Waypoint system.
WP_ , WN_ , POST_ , NIGHT_
Each waypoint has a prefix (as shown above) followed by the TAG of the NPC.
So if your NPC had a tag of SMITH then the waypoint tags would be,
WP_SMITH, WN_SMITH, POST_SMITH, and NIGHT_SMITH
WP_ Waypoints: These waypoints are used to move your NPC around in the day.
WN_ Waypoints: These waypoints are used to move your NPC around at night.
POST_ Waypoints: Used to make your NPC walk to one spot and stay there at daytime.
NIGHT_ Waypoints: Used to make your NPC walk to one spot and stay there at night time.
The NPC can have multiples of the WP_ and WN_ waypoints,
but only one POST_ and one NIGHT_ waypoint.
Multiples of the WP and WN waypoints have a sequence number at the end of the tag name,
so for the NPC called SMITH, the waypoints would be;
WP_SMITH_01, WP_SMITH_02, WP_SMITH_03, etc....
The POST waypoint cannot be used with WP waypoints for a given NPC.
The WP waypoints override POST waypoints.
A similar rule applies to NIGHT waypoint not being used with WN waypoint
WN waypoints override NIGHT waypoint.
This means you cannot have the NPC run a set pattern of WP_ waypoints to then stand at
a POST_ waypoint.

The easiest way of getting the waypoints up and running for your npc is;
Right click on your npc and choose create waypoint.
A waypoint is created underneath or near the npc.
Move the mouse to the point on screen you want your second waypoint to appear, and then
right click, the option to create a waypoint is given.
Choosing create waypoint will create a second waypoint for your NPC.
This process can be done multiple times.
To get a guard to return to his barracks at night.
If the guard has a tag of GUARD, then place a NIGHT_GUARD waypoint in the barracks.
This can be used with a sequence of WP waypoints for your guard to patrol in the day,
e.g. WP_GUARD_01, WP_GUARD_02, etc
Or it can be used with a POST waypoint tagged POST_GUARD to have him stand at his post in the
day.
To allow for cross area transitions, e.g. Barracks in one area, patrol route in another.
You will need to set the global int X2_SWITCH_CROSSAREA_WALKWAYPOINTS to one on
the module.
To do this;
In module properties, click the advanced tab, then click variables.
Enter X2_SWITCH_CROSSAREA_WALKWAYPOINTS as an int and the value to 1.
My guard gets stuck crossing area transitions.(or is going a strange route)
You will have to experiment with this, due to some issues with the path finding.
If your area has more than one transition point to a second (but same) area then do not expect
your NPC to use the transition point you want.
It may be best to experiment using POST and NIGHT waypoints first to see which route the
NPC favours.
Its worth knowing this, so you know why its happening, and you don'
t waste too much time,
like I have
My NPC is getting stuck on walls.
This is due to the AI on NPC'
s being set to low if a player is not in the area.
One of the best ways to get around this is to have more WP, WN waypoints if you can to help
the NPC path find a lot better.
Obviously this won'
t help POST and NIGHT waypoints, but if you know scripting you could place
a script on enter of an area to check if any players are in the area and if not, jump the NPC
to its POST or NIGHT waypoint.
See the AI section below if you need the NC to move around regardless of PC'
s being present in the
area.

My NPC is not facing the same direction as his waypoint when at a POST or NIGHT waypoint.
Right-click the Waypoint and go to variables.
Enter X2_L_WAYPOINT_SETFACING as an int and the value to 1.
My NPC is not changing to its NIGHT_ or WN waypoints at night time.
Right-click the NPC and go to variables.
Enter NW_GENERIC_MASTER as an int and the value to 4194304
(the value listed above is for day/night posting only - see the section below on the
NW_GENERIC_MASTER settings.)
My NPC doesn't seem to want to walk to their waypoints
Ensure that the NW_GENERIC_MASTER has not been set for the
NW_FLAG_AMBIENT_ANIMATIONS or
NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS settings. (see the section below)
WAYPOINTS USED WITH AMBIENT ANIMATIONS
The following Waypoints require that ambient animations be switched on at spawn time
of the NPC.
That means that the following variable needs to be set on the NPC.
Right-click the NPC and go to variables.
Enter NW_GENERIC_MASTER as an int and the value to 524288
When ambient animations is switched on for a NPC, the NPC will wander around and
interact with other NPC'
s that have either ambient or immobile ambient animations switched on.
They will also interact with nearby placeables. Walking up to a placeable, closing nearby doors.
Also worth noting that the NPC'
s will also use the same animations for ambient animations,
as they do for immobile ambient animations (with a bit more moving around).
The NPC with ambient animations switched on will never wander too far from its spawn
point(starting position), always returning back to it.
The following waypoints allow for better control of your NPC'
s.
To wander around more between the waypoints described below, as well as the placeables the NPC
comes across, or the other NPC'
s, or its spawn point(start position).
Remember - The NPC'
s will not walk straight to these waypoints as in walkwaypoints above but
will casually walk around and occasionally walk to one of them.

Generic Stop Waypoint


This waypoint is tagged "NW_STOP".
If you place a few of these in an area, lets say a city exterior for example.
If the NPC'
s spawned in that area have ambient animations switched on, they will occasionally walk
amongst the NW_STOP waypoints.
This works quite well if you want a busy/crowded city/town feel.
So you could have a park area in the city with an NW_STOP waypoint, or/and a NW_STOP
waypoint
near a market stall.
The NPC'
s spawned in that are will at some point in their wanderings go to these waypoints.
Tavern Waypoint
This waypoint is tagged "NW_TAVERN".
NPC'
s with ambient animations switched on which are spawned inside an area with the tavern
waypoint,
will remain in the tavern and not leave it.
However, for NPC'
s spawned outside the tavern area,
If you place a NW_STOP waypoint inside the tavern as well (as the NW_TAVERN),
The NPC'
s will cross the area transition to visit the NW_STOP waypoint
in the Tavern, neatly closing the door behind them on entry/exit of the tavern/area outside.
Any NPC with ambient animations will use the drinking animation more in an area with a
NW_TAVERN waypoint.
Shop Waypoint
This waypoint is tagged "NW_SHOP".
Like the tavern waypoint, if an NPC is spawned inside an area with the shop waypoint then
the NPC will remain in the shop and not leave it (the shop keeper/assistant I guess).
If an NPC is spawned outside the shop area,
If you place a NW_STOP waypoint inside the shop as well, the NPC will cross the area transition
to visit the NW_STOP waypoint, neatly closing the door behind them on entry/exit of the shop.
Home waypoint
This waypoint is tagged "NW_HOME".
If an npc is spawned in an area that that has a home waypoint then the NPC will class that
area as his home.
what should happen is the NPC will leave the area in the day and return to it at night.

After long testing, the NPC only seemed to want to leave the area if a player entered it,
however the NPC did return back to the area at night.
This is due to the AI level of the creature.
See the AI section below if you need the NC to move around regardless of PC'
s being present in the
area.
Safe Waypoint
This waypoint is tagged "NW_SAFE".
Placing one of these waypoints in area, means that any injured NPC with ambient animations
will retreat to this point.
Sort of like a cowering corner.
NPC'
s will not cross area transitions to get to a NW_SAFE waypoint.
If there is not a NW_SAFE waypoint in the same area then they will resume ambient animations.
Stealth Waypoint
This Waypoint is tagged "NW_STEALTH".
Placing one of these waypoints in an area, means any NPC with stealth capabilities that reaches
one of these waypoints, turns stealth mode on.
Could be good for using in dark caverns/dungeons etc, to have NPC disappear into and appear from
the darkness.
Detect waypoint
This Waypoint is tagged "NW_DETECT".
Placing one of these waypoints in an area, means any NPC that reaches one of these waypoints,
turns detect mode on.
Again, could be good for using in dark caverns/dungeons etc, to have NPC'
s start to detect hiding
PC'
s.
My NPC is not wandering around even though mobile animations is switched on.
Ensure that the NW_GENERIC_MASTER variable has been set on the NPC for
NW_FLAG_AMBIENT_ANIMATIONS
and not NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS.

Can I use NW_STOP waypoints inside NW_TAVERN,NW_SHOP waypointed areas?


The answer is yes.
You will need to place NW_STOP waypoints in the NW_TAVERN,NW_SHOP areas if you want
the NPC'
s outside to come and drink/shop
BEHOLDER AI EXIT WAYPOINT
This waypoint is tagged "X2_WP_BEHOLDER_TUNNEL"
If you look in the script "x2_ai_behold" it tells you what the waypoint is for.
It explains;
Beholder will always use its eyes, unless
a) If threatened in melee, it will try to move away or float away
to the nearest waypoint tagged X2_WP_BEHOLDER_TUNNEL
So if you place a few of these waypoints around, your beholder will escape to the nearest one.
If you noticed in Chapter two of HotU these waypoints where placed on the other side of
room doors.
NW_GENERIC_MASTER VARIABLE SETTINGS
To use these, add a variable to an NPC called NW_GENERIC_MASTER,
and assign one of these values, or the sum of all the values you want to use to the variable:
NW_FLAG_AMBIENT_ANIMATIONS = 524288
NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 2097152
NW_FLAG_DAY_NIGHT_POSTING = 4194304
AI SETTINGS
The default AI will mean that your NPC'
s will not move around if there is no PC present in their
current area.
IF you want your NPC'
s to move around regardless of PC'
s being present, you will have to set their
AI level in the NPC'
s
onspawn script.
Open up the NPC'
s properties, and select the SCRIPTS tab.
edit the onspan script for the NPC by clicking on the '
edit'button at the side of the onspawn script.

Paste the following line into the script;


SetAILevel(OBJECT_SELF,AI_LEVEL_LOW);
this needs to placed just after the '
void main {'
, eg;
void main()
{
SetAILevel(OBJECT_SELF,AI_LEVEL_LOW);
Then save the script as another name, so that not all your NPC'
s are affected by the AI setting
change.
I advice that you only set the AI level of a few NPC'
s that you really want to move regardless of PC
proximity.
(this is because setting the AI higher on an NPC can cause lag).
OTHER GUIDES/SYSTEMS
Rhones Hour-based Waypoint Walker system is an advanced system which allows you to use both
ambient animations and waypoints together (unlike the standard bioware walkwaypoints)
----------------------------------Thanks for reading through all this, I just felt like sharing this all over again.

You might also like