In Ryzom Core we have one main NPC that randomly chats to you. You can take a look at how he chats you up about the four freedoms but you might want some more explanation. This also isn't the only way to make your NPCs talk your players ears off so lets see how Chiang works and then maybe expand his capabilities a little bit...
Random Chatter Using Timers
This is accomplished using a
timer_t0_triggered NPC group event handler and a
start_of_state NPC group event handler. The logic here is pretty simple: you use the
start_of_state to set your
t0 timer. In the case of Chiang the Strong it is set to 1000. This timer value uses
in game ticks which is an important distinction. Many people would assume it is seconds or milliseconds. In timing terms there are 10 game ticks per real second so a value of 1000 is approximately every 100 seconds.
So now you have a timer that will go off in 10 seconds. You need to tie that timer to something. In the same NPC group you'll add another NPC group event handler to handle the
timer_t0_triggered event. So now when your timer, created above, goes off it will get caught by this new event handler. In this event handler you need to do two things: set the timer again so he keeps chatting and then randomly say something. In order to accomplish two things your first action will be a
multi_action which just allows you to specify more than one
npc_event_action object. It will execute all of these actions.
The first action you'll add is a new
set_timer_t0 action, it is set up the same way as your initial
start_of_state but in the case of the Ryzom Core example we change the duration to 1500 - so he's a little less chatty. This new action sets the chatter loop in motion.
Next we'll add a
random_select action. Here's a quick hint - most of these types are documented and you can see the local documentation in your favorite browser by clicking "View" next to the action drop down. You'll see this pattern throughout the classic World Editor tool. The documentation for
random_select states the random choice is based on weight. This isn't true, it doesn't work. If you need it to work please log a bug. Under the random selection action you'll see that Chiang says four things - this is because he chats about the
four freedoms all day long. So just keep adding
say actions to your hearts content and he'll keep adding new things to babble about. You'll see that the say parameters are formatted like this:
say: CHIANG_1
You have a number of options in the
say action parameters: tell, say, shout, universe, escort. I'm not really going to go into detail on these as for the most part they make sense. If you want your NPC to shout something you would use "shout" instead of "say". The second component, the
CHIANG_1 is a phrase ID. Lets say you want Chiang to also say "Hey, by the way, Affero GPL is the best!" you would add a new
say action with a phrase ID of something like
CHIANG_5 or maybe
CHIANG_AFFERO since the phrase ID is some what arbitrary. Let us assume you add
CHIANG_5. Add your new action and set that for the parameter. Then you need to actually define that phrase somewhere. The details of translation are for another tutorial but to cut to the chase you would modify the phrase_XX.txt (where XX represents your various supported languages, e.g. en or fr) and add a new line there. It should be present in the phrase files on both the server and the client.
That's it, now Chiang says one more thing.
Mixing It Up
You can see how we can use a timer to quickly add repeatitive chatting but really you can use almost any NPC event. For example you could modify the NPCs In Motion tutorial so that the begin_state event handler has a multi_action where one action says a phrase like "Alright, lets get going" and the next action starts the guards in motion on the path.
Another popular alternative is to use the player_target_npc event handler - actions in this event handler get called whenever a player targets the NPC. When using this event handler type you have a player component and so instead of using the "say" parameter you could use the "tell" parameter.