Conversations

From The DarkMod Wiki
Revision as of 18:49, 20 October 2015 by VanishedOne (talk | contribs) (→‎Conversation: Note on conv_N_actors_must_be_within_talkdistance and seated AI)
Jump to navigationJump to search

Conversations between AI have a HUGE impact on player immersion, and they're not hard to do.

If you have no way to record dialogue, you can always look through the vocal sets...it's quite possible to create short conversations with barks that already exist.

Overview

All the info regarding a conversation is contained within a atdm:conversation_info entity. Each of these entities can define one or more conversations. There is a custom conversation editor GUI for DarkRadiant (on the map menu), which is the easiest way to make and edit them; but you can add these entities yourself and set the spawnargs manually if you wish.

For instructions on how to use the conversation editor, see: Cutscenes Part 3: Lighting, Placing the Player, and Conversations or Conversation Tutorial.

Each conversation can have one or more Actors. These are the AI which will participate in the conversation.

Each conversation consists of a sequence of so-called Conversation Commands, which are specific actions you can use to make the actors do what you want them to. Examples are "Talk", "Attack", "WalkToEntity", etc. You can add as many conversation commands as you like.

Add a Conversation Info entity

Right-click somewhere in the grid view and hit "Create Entity" which will open the dialog for selecting the entity classes. Go to Conversation and select atdm:conversation_info.

(Note, make sure the entity isn't 'in the void' or you will get a leak in your map. Otherwise, it doesn't matter where the entity is placed.)

Add the conversation spawnargs

Once the entity is created you can start defining your conversation. The easiest way is to use the conversation editor.

Here is an example of a simplistic "conversation" containing exactly one command:

"conv_1_name" "Testconversation 1"                // defines the name of the conversation (mandatory)
"conv_1_actor_1" "atdm:ai_builder_guard_1"        // first actor
"conv_1_actor_2" "atdm:ai_builder_guard_2"        // second actor

// Here's the first conversation command (defined as cmd_1)
"conv_1_cmd_1_actor" "1"                          // Actor 1 takes this action
"conv_1_cmd_1_type" "Talk"                        // the action is "Talk"   (uppercase T is required)
"conv_1_cmd_1_arg_1" "tdm_test_conversation_1_1"  // play the sound shader: 'tdm_test_conversation_1_1'

So basically, this conversation has a name Testconversation 1, two actors (builder_guard_1 and 2) and lets the actor 1 play the sound shader tdm_test_conversation_1_1.

As you can see, the naming convention for the spawnargs is like this:

conv_<number>_<key>

The purpose of <number> is to distinguish multiple conversations defined on the same conversation info entity. You can use a single entity for all the conversations in your map if you wish, although you'll probably want to keep them separate in order to trigger them at different times (see below).

The <key> is then defining the properties and commands of this conversation. Each conversation can have multiple commands, that's why these spawnargs are equipped with indices as well ("conv_1_cmd_N_...").

The above example is defining a command called Talk. There are more conversation commands available, each having a varying number of arguments. See the section below for details.

Each conversation must have a name and at least one actor and one command, otherwise the parser will flag the conversation as invalid and it will therefore be ignored.

Note: The <number> value is always numeric and starts with 1.

Spawnargs

Conversation

These spawnargs can be used to define properties that affect the conversation as a whole.

The first two MUST be set by the mapper; the rest have defaults and only need to be changed if you want a non-standard result.

The uppercase N indicates the conversation number (starting from 1).

conv_N_name (string)
defines the name of the conversation. This is a mandatory spawnarg, a conversation without a name will be ignored.
conv_N_actor_Y (entity name)
define the names of the AI participating in this conversation. At least one actor is required, otherwise the conversation is invalid.


The following are optional:

conv_N_actors_must_be_within_talkdistance (1/0) default is 1
if set to "1", all actors are told to walk towards each other before the conversation actually starts. (Note that this can make seated characters stand up while the conversation plays even if they don't need to walk anywhere.)
conv_N_talk_distance (float) default is 60
defines the maximum distance AI should be away from each other while talking. When the spawnarg actors_must_be_within_talkdistance is set to 1, this distance tells the AI when to stop when walking towards each other.
conv_N_actors_always_face_each_other_while_talking (1/0) default is 1
if set to "1", all actors are facing each other while talking. The talker turns towards another actor (usually the actor 0 or 1), and all other actors (the listeners) turn to face the talker. Note that when this option is selected in the conversation editor, AI will randomly play talk animations while speaking. When it is not selected, they won't. The latter may be desirable when AI are talking to themselves or whistling, for example
conv_N_max_play_count (int) default is -1
defines the maximum number of times this conversation is allowed to "play". After this number has been exhausted, the conversation won't be started anymore.
conv_N_cmd_Y_...
the conversation commands (see below). One conversation must have at least one and is allowed to have multiple conversation commands.

Conversation Commands

These spawnargs are used to tell the actors what to do during the conversation.

The prefix conv_N_ refers to the conversation these commands are associated with. The number M refers to the command number (starting at 1).

conv_N_cmd_M_actor (integer actor number, starting from 1)
defines which actor should perform this command. Use the "Actor Number" you assigned earlier. Note that the value of this spawnarg is a number X referring to the conv_N_actor_X definition above. You address a conversation's actor by this number, not by its name. ;conv_N_cmd_M_type (string == command type name)
defines the type of command you want to give (this is a mandatory spawnarg, each command must have a type). The most common is probably "Talk". See below for a list of available type names. Ex: "conv_1_cmd_1_type" "Talk"
conv_N_cmd_M_wait_until_finished (1/0), default is 1 (note
default is 0 in the editor)
defines whether the conversation should wait for the actor to complete this command before the next command is executed. Setting this to "0" allows to step over to the next command with nearly no time loss. This can be used to issue two or more commands at virtually the same time to an actor, so that the commands "Talk" and "PlayAnimOnce" are executed side-by-side by the same AI, for instance.

Note: I set a single conversation for an AI to walk to an entity. This failed unless this spawnarg was set to 1 so possibly the last command in the list needs it?

conv_N_cmd_M_arg_L
defines the arguments of this conversation command. The actual arguments depend on the command type, each type is requiring a different amount of arguments, and some of them are optional. See below for a description of the command's arguments. The index L starts at the number 1, there is no upper limit imposed by the code.

Triggering a Conversation

Now that your conversation is created, you need to trigger it.

To trigger a conversation you need to create a target_tdm_startconversation entity. Give it the spawnarg "conversation" with the name of the conversation you want to start (ex "conversation" "Testcoversation 1") then target that entity from any trigger you like such as a trigger_once entity or path node (as of TDM v2.02).

Conversation Commands

The following is a list of available conversation commands:

  • WaitSeconds
Lets the actor wait the given amount of seconds. Note that the wait_until_finished property is not affecting this command (would be pointless).
  • Argument 1: (float) The amount of seconds to wait.
  • WalkToActor
Lets the actor walk to another actor, which must be participating in this conversation.
  • Argument 1: (integer) The actor number of the AI to walk to.
  • Argument 2: (optional float) The distance at which the actor stops "before" the actor. This value is optional and defaults to 50.
  • WalkToPosition
Lets the actor walk to the given position.
  • Argument 1: (vector) The world position to walk to (e.g. "-32 4 196").
  • WalkToEntity
Lets the actor walk to the given entity.
  • Argument 1: (string) The name of the entity to walk to.
  • Argument 2: (optional float) The distance at which the actor stops "before" the entity. This value is optional and defaults to 50.
  • StopMove
Tells the entity to stop its current movement (no arguments).
  • Talk
Lets the actor talk a given string.
  • Argument 1: (string) The sound shader to play
  • Argument 2: (optional string) The language string to display as subtitle in the #str_9NNNN format. Conversation strings should start in the 9xxxx number range and are defined in the strings/*.lang file. Note: this feature is not yet implemented.
  • PlayAnimOnce
Lets the actor play an animation once.
  • Argument 1: (string) the name of the animation to play (see the actor's modelDef file)
  • Argument 2: (optional integer) the number of blendframes to use when switching anims. This is optional and defaults to 4.
  • PlayAnimCycle
Lets the actor play an animation over and over. Note that the property wait_until_finished is not allowed here, as this command never stops, so execution will immediately proceed to the next command.
  • Argument 1: (string) the name of the animation to play (see the actor's modelDef file)
  • Argument 2: (optional integer) the number of blendframes to use when switching anims. This is optional and defaults to 4.
  • ActivateTarget
Triggers the given entity.
  • Argument 1: (string) the name of the entity to trigger.
  • LookAtActor
Lets the actor look at another actor (must be participating in the conversation).
  • Argument 1: (integer) the actor number of the AI to look at.
  • Argument 2: (optional float) the "look duration" in seconds, the head is turning back to its previous position afterwards. This is optional and defaults to 5 seconds.
  • LookAtPosition
Lets the actor look at the given position.
  • Argument 1: (vector) the world position to look at (e.g. "-32 4 196").
  • Argument 2: (optional float) the "look duration" in seconds, the head is turning back to its previous position afterwards. This is optional and defaults to 5 seconds.
  • LookAtEntity
Lets the actor look at the given entity.
  • Argument 1: (string) the name of the entity to look at.
  • Argument 2: (optional float) the "look duration" in seconds, the head is turning back to its previous position afterwards. This is optional and defaults to 5 seconds.
  • TurnToActor
Lets the actor turn towards the given actor, which must participate in this conversation too (the whole body is rotated towards the actor). This command has no duration, so the property wait_until_finished is effectless here.
  • Argument 1: (integer) the actor number of the AI to turn towards.
  • TurnToPosition
Lets the actor turn towards the given position (the whole body is affected). This command has no duration, so the property wait_until_finished is effectless here.
  • Argument 1: (vector) the position in world coordinates which the actor should turn towards (e.g. "-32 4 196").
  • TurnToEntity
Lets the actor turn towards the given entity (whole body is affected). This command has no duration, so the property wait_until_finished is effectless here.
  • Argument 1: (string) the entity to turn towards.
  • AttackActor
Lets the actor attack the other actor (which must be partipicating in this conversation as well). This command has no duration, so the property wait_until_finished is effectless here.
  • Argument 1: (integer) the actor number of the AI to attack.
  • AttackEntity
Lets the actor attack the given entity (which can be any other AI or any other player). This command has no duration, so the property wait_until_finished is effectless here.
  • Argument 1: (string) the entity to attack (e.g. "player1").
  • InteractWithEntity
Lets the actor walk to an entity, play the "use" anim and trigger the entity's frobaction script. Doors will be opened, buttons be pushed, etc.
  • Argument 1: (string) the entity to interact with.
  • RunScript
Runs a local or global script function. Local script functions (those defined on the actor's scriptobject) must not take any arguments, global scriptfunctions must take an entity as argument (the actor will be passed as "owner" to this global function). Note that if wait_until_finished is set to "1" the command will not finish until the script is completely done (i.e. non-terminating eachFrame loops within the script function would cause this command to last forever).
  • Argument 1: (string) the name of the local or global script function.
  • WaitForActor
Lets the actor wait until the other actor (specified in the first argument) has finished executing his current conversation command. If the other actor is already done with his command, WaitForActor does nothing.
  • Argument 1: (integer) the actor number of the AI to wait for.
  • WaitForAllActors
Lets the conversation wait until all actors are finished executing their commands. Afterwards the conversation is allowed to continue with the next command.
  • no arguments

How to get AI to patrol after finishing a conversation

Sometimes you want AI to stay put until their conversation is triggered, and then start a regular patrol. Here's one way how(courtesy of grayman), see another below in Notes:

Guards Bob and Sam will have the conversation. Neither is targetted at any path_corners.

When the conversation is over, you want Bob to start patrolling, starting with path_corner_1.

When the conversation is over, you want Sam to start patrolling, starting with path_corner_2.

A player-activated trigger fires the entity that starts the conversation.

In the conversation, have these two steps at or near the end:

Trigger the entity StartBobPatrol

Trigger the entity StartSamPatrol

"StartBobPatrol" is an atdm:target_changetarget with these spawnargs:

"add" "path_corner_1" "target" "Bob"

"StartSamPatrol" is an atdm:target_changetarget with these spawnargs:

"add" "path_corner_2" "target" "Sam"

When the conversation ends, both guards will go their separate ways.

Notes

  • It's possible to define conversations with only one actor. This can be used to let AI talk a single sentence or perform some other actions.
  • The flags actors_must_be_within_talkdistance and actors_always_face_each_other_while_talking have no effect when only one actor is present in the conversation. The flags are automatically set to 0 in the code.
  • Starting with 1.08, an actor who begins a conversation sitting on a path_waitfortrigger can be moved off that trigger at the end of the conversation by having the last step in the conversation activate a trigger_once whose target is the actor, and which has a 'delay' spawnarg set to at least 1 second. W/o the delay, the actor will ignore the activation and remain where they are.
  • Simpler to walk off might be to have the last command in your conversation trigger an atdm:target_changetarget. In that entity, give it these spawnargs: "target" "<name of AI who's leaving>" and "add" "<name of path_corner you want him to walk to>"

Volume of Custom Lines

The soundshader files for unique lines control how far the sound reaches and volume, it's not set within the editor.

minDistance 1
maxDistance 25
volume 1

Regular AI spoken lines have maxDistance 25, yells 30.

Debugging Conversations

There are several possibilities to debug conversations, in case something isn't working correctly:

  • The CVAR tdm_ai_show_conversationstate (when set to 1) draws the current conversation command and its execution state on all AI which are currently involved in conversations.
  • Another way to check if things go wrong is the console. During map load the number of valid conversations found in the map is verbosed to the console, so be sure to check if this number is right. If this number differs from the number you should have, you probably have your spawnargs wrong. Warnings might also be printed to the console if things go wrong during the execution of conversation commands.
  • The log file gives you some insight what is happening in the conversation code during map load and during the actual conversations. Open your darkmod.ini file and set LogClass_CONVERSATION to 1 to enable conversation logging. Also, be sure to enable the various log types (ERROR, DEBUG, WARNING and INFO) to see all the messages.