Tuesday, August 28, 2012

Tutorial: Chatty NPCs

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.


  1. I don't want to nit-pick but if 1000 ticks are round about 10 seconds then there are 100 ticks per second and not 10

  2. Jarnar a,

    Thanks for the correction. It is 10 ticks per second so 100 seconds. I'll correct the tutorial.