Conversations: Difference between revisions
Lou Montana (talk | contribs) m (Fix) |
Lou Montana (talk | contribs) m (Some wiki formatting) |
||
(5 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{TOC|side}} | {{TOC|side}} | ||
{{GVI|arma2|1.00}} {{GVI|arma2oa|1.50}} {{GVI|TKOH|1.00}} {{GVI|arma3|1.00}} | |||
[[Conversations]] is a system created to manage discussions that was introduced in '''{{arma2}}'''. | |||
[[Conversations]] is a system created to manage discussions | |||
This system allows dynamic conversations and a more fluid sentence/answer flow. | This system allows dynamic conversations and a more fluid sentence/answer flow. | ||
Line 36: | Line 33: | ||
* Related functions are listed in [[:Category:Function Group: Conversations|Conversations Function Group]] | * Related functions are listed in [[:Category:Function Group: Conversations|Conversations Function Group]] | ||
=== Manual Conversation Example === | |||
=== Manual | |||
<sqf> | <sqf> | ||
miles | miles kbAddTopic ["briefing", "kb\briefing.bikb"]; | ||
shaftoe kbAddTopic ["briefing", "kb\briefing.bikb"]; | shaftoe kbAddTopic ["briefing", "kb\briefing.bikb"]; | ||
shaftoe kbTell [miles, "briefing", "shaftoe_briefing_H_1"]; | shaftoe kbTell [miles, "briefing", "shaftoe_briefing_H_1"]; | ||
Line 65: | Line 61: | ||
A duplicate sentence in .bikb file '''WILL''' crash the game!}} | A duplicate sentence in .bikb file '''WILL''' crash the game!}} | ||
=== "Interrupted" Event === | |||
=== "Interrupted" | |||
The left-side conversation menu (with the list of possible sentences) can be closed via backspace at all times. In order to handle this event as well, add a sentence class called '''Interrupted''' into the .bikb file. It can then be used as a standard {{hl|_sentenceId}} in the script. | The left-side conversation menu (with the list of possible sentences) can be closed via backspace at all times. In order to handle this event as well, add a sentence class called '''Interrupted''' into the .bikb file. It can then be used as a standard {{hl|_sentenceId}} in the script. | ||
=== .bikb Simple Example === | |||
=== .bikb | |||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
Line 90: | Line 84: | ||
class good_you | class good_you | ||
{ | { | ||
text = $STR_GoodYou; // has to start with "STR_"! | text = "$STR_GoodYou"; // has to start with "STR_"! | ||
speech[] = { "\Sound\good_you.ogg" }; | speech[] = { "\Sound\good_you.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 96: | Line 90: | ||
class fine_thanks | class fine_thanks | ||
{ | { | ||
text = $STR_FineThanks; | text = "$STR_FineThanks"; | ||
speech[] = { "\Sound\fine_thanks" }; // no extension means .wss to the engine | speech[] = { "\Sound\fine_thanks" }; // no extension means .wss to the engine | ||
class Arguments {}; | class Arguments {}; | ||
Line 102: | Line 96: | ||
// these sentences are here to be a full example for later Conversation Event Handler example | // these sentences are here to be a full example for later Conversation Event Handler example | ||
class what_do_we_do { text = "What do we do today?"; speech[] = { "\Sound\wdwd.ogg" }; class Arguments {}; }; | class what_do_we_do { text = "What do we do today?"; speech[] = { "\Sound\wdwd.ogg" }; class Arguments {}; }; | ||
class choose_football { text = "Let's football!"; speech[] = { "\Sound\cf.ogg" }; class Arguments {}; }; | class choose_football { text = "Let's football!"; speech[] = { "\Sound\cf.ogg" }; class Arguments {}; }; | ||
class choose_bike { text = "Let's bike?"; speech[] = { "\Sound\cb.ogg" }; class Arguments {}; }; | class choose_bike { text = "Let's bike?"; speech[] = { "\Sound\cb.ogg" }; class Arguments {}; }; | ||
Line 124: | Line 118: | ||
=== .bikb | === .bikb Advanced Example === | ||
See [[Arma_3_Radio_Protocol#Words|Words configuration]] and below for more details. | See [[Arma_3_Radio_Protocol#Words|Words configuration]] and below for more details. | ||
Line 163: | Line 157: | ||
</sqf> | </sqf> | ||
=== .bikb BIS_fnc_kbTell | === .bikb BIS_fnc_kbTell Example === | ||
{{Feature|arma3| | {{Feature|arma3| | ||
Line 172: | Line 166: | ||
{ | { | ||
text = ""; // must be empty | text = ""; // must be empty | ||
textPlain = $STR_MySubTitle; | textPlain = "$STR_MySubTitle"; | ||
/* other parameters */ | /* other parameters */ | ||
}; | }; | ||
Line 220: | Line 214: | ||
class Sentence1 | class Sentence1 | ||
{ | { | ||
text = $STR_HelloThere; | text = "$STR_HelloThere"; | ||
speech[] = { "\Sound\hello.ogg" }; | speech[] = { "\Sound\hello.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 226: | Line 220: | ||
class Sentence2 | class Sentence2 | ||
{ | { | ||
text = $STR_GeneralKenobi; | text = "$STR_GeneralKenobi"; | ||
speech[] = { "Sound\gk.ogg" }; | speech[] = { "Sound\gk.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 232: | Line 226: | ||
class Sentence3 | class Sentence3 | ||
{ | { | ||
text = $STR_YouAreABoldOne; | text = "$STR_YouAreABoldOne"; | ||
speech[] = { "Sound\bold.ogg" }; | speech[] = { "Sound\bold.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 250: | Line 244: | ||
class Sentence1 | class Sentence1 | ||
{ | { | ||
text = $STR_HelloThere; | text = "$STR_HelloThere"; | ||
speech[] = { "\Sound\hello.ogg" }; | speech[] = { "\Sound\hello.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 257: | Line 251: | ||
class Sentence2 | class Sentence2 | ||
{ | { | ||
text = $STR_GeneralKenobi; | text = "$STR_GeneralKenobi"; | ||
speech[] = { "Sound\gk.ogg" }; | speech[] = { "Sound\gk.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 264: | Line 258: | ||
class Sentence3 | class Sentence3 | ||
{ | { | ||
text = $STR_YouAreABoldOne; | text = "$STR_YouAreABoldOne"; | ||
speech[] = { "Sound\bold.ogg" }; | speech[] = { "Sound\bold.ogg" }; | ||
class Arguments {}; | class Arguments {}; | ||
Line 296: | Line 290: | ||
{{Feature|important|Please note: | {{Feature|important| | ||
Please note: | |||
* use '''class CfgSentences''' in [[Description.ext]] | * use '''class CfgSentences''' in [[Description.ext]] | ||
* use '''class Sentences''' in .bikb files}} | * use '''class Sentences''' in .bikb files | ||
}} | |||
Line 311: | Line 307: | ||
See also: [[FSM]], [[FSM Editor]] | See also: [[FSM]], [[FSM Editor]] | ||
=== Conversation FSM Example === | |||
[[File:ConversationFSM_example.png|thumb|left|800px|A simple FSM that AI uses to react to a speaker's sentences]] | |||
[[ | |||
{{Clear}} | {{Clear}} | ||
Line 320: | Line 315: | ||
== Conversation Event Handler == | == Conversation Event Handler == | ||
The '''Conversation Event Handler''' is | The '''Conversation Event Handler''' is code, provided through [[kbAddTopic]], that is executed with each sentence '''received by a player''', and will constantly fire ([[onEachFrame]]) when the player is pointing at a "talkable" person at "talkable" range. Following parameters are passed: | ||
* '''_this:''' [[Object]] - the [[player]] receiving the sentence. Must have had this particular script assigned ''via'' [[kbAddTopic]] | * '''_this:''' [[Object]] - the [[player]] receiving the sentence. Must have had this particular script assigned ''via'' [[kbAddTopic]] | ||
* '''_from:''' [[Object]] - the unit that told the sentence | * '''_from:''' [[Object]] - the unit that told the sentence | ||
Line 327: | Line 321: | ||
* '''_topic:''' [[String]] - topic name used in [[kbAddTopic]] | * '''_topic:''' [[String]] - topic name used in [[kbAddTopic]] | ||
Its return format is an [[Array]] of arrays (or an empty array) | {{Feature|informative|This Conversation Event Handler is '''not''' an [[:Category:Event Handlers|Event Handler]] as we know them.}} | ||
Its return value is used to provide the player's available replies; its format is an [[Array]] of arrays (or an empty array) that can look like this: | |||
<sqf> | <sqf> | ||
[ | [ | ||
Line 347: | Line 343: | ||
There is a certain resemblance with the [[kbTell]] syntax; note that the ''forceRadio'' parameter is not present. | There is a certain resemblance with the [[kbTell]] syntax; note that the ''forceRadio'' parameter is not present. | ||
{{Feature|important|The Conversation Event Handler's code is executed in [[Scheduler#Unscheduled_Environment|'''unscheduled''' environment]] | {{Feature|important|The Conversation Event Handler's code is executed in [[Scheduler#Unscheduled_Environment|'''unscheduled''' environment]] - be sure to not use [[sleep]] or any other [[Scheduler]]-incompatible commands.}} | ||
=== Conversation Event Handler | === Conversation Event Handler Example === | ||
<sqf> | <sqf> | ||
Line 397: | Line 392: | ||
== See | == See Also == | ||
* [[:Category:Command Group: Conversations|Conversations Command Group]] | * [[:Category:Command Group: Conversations|Conversations Command Group]] | ||
* [[:Category:Function Group: Conversations|Conversations Function Group]] | * [[:Category:Function Group: Conversations|Conversations Function Group]] | ||
* {{ | * {{Link|https://forums.bohemia.net/forums/topic/89071-new-conversation-system-how-to/|Jezuro's introduction forum post}} | ||
* {{ | * {{Link|https://forums.bohemia.net/forums/topic/107662-using-dialogue-system-between-player-and-ai/|HateDread's forum post and Evil_Echo's answers}} | ||
* [[FSM]] | * [[FSM]] | ||
* [[FSM Editor]] | * [[FSM Editor]] |
Latest revision as of 21:01, 22 September 2024
Conversations is a system created to manage discussions that was introduced in Arma 2. This system allows dynamic conversations and a more fluid sentence/answer flow.
Its main advantages are:
- The system itself waits for the sound sample to finish. No more sample time measuring and countless sleeps!
- Conversation always flows through the appropriate channel (direct for face to face, team radio for distant team members etc.)
- Possibility to create fully dynamic conversations
- Transparent syntax (FSM branches allow fast and efficient edits)
Usage
- A topic is defined by a String for id and sentences defined in a Conversation .bikb file
- A Conversation .bikb lists all available sentences in a topic
- A topic must be added to the concerned units, with eventually a Conversation FSM and/or a Conversation Event Handler
- A Conversation FSM defines an AI unit reaction to a sentence
- A Conversation Event Handler defines a player's unit reaction to a sentence, potentially defining available answers
- If the unit is playable (can be either player or AI), both should be present to ensure a proper reaction in every encountered scenario.
Commands
A conversation topic:
- must be added to units (via kbAddTopic)
- for the units to be able use it (via kbTell for example)
- once the unit said wanted sentences (checked via kbWasSaid),
- the topic can be removed (via kbRemoveTopic).
- Related commands are listed in Conversations Command Group
- Related functions are listed in Conversations Function Group
Manual Conversation Example
Conversation .bikb
.bikb extension stands for "Bohemia Interactive Knowledge Base" as it was originally used only for storing an AI unit's memory of what it has seen.
This file declares the available sentences in the topic, their sound samples and the corresponding subtitles (see example 1 and example 2).
As the syntax is the same as config files (Description.ext, Config.cpp) PreProcessor Commands can be used.
Conversation sounds do not need to be defined in CfgSounds or CfgRadio, unless of course they are to be used with e.g playSound, say or groupRadio too.
As opposed to these commands, this new conversation system will automatically use setRandomLip during the speech if no .lip file is present. A .lip file can however still be used for a more precise animation.
"Interrupted" Event
The left-side conversation menu (with the list of possible sentences) can be closed via backspace at all times. In order to handle this event as well, add a sentence class called Interrupted into the .bikb file. It can then be used as a standard _sentenceId in the script.
.bikb Simple Example
class Sentences
{
class hello1
{
text = "Hello!"; // sentence subtitle - can be "text" or $STR_ stringtable reference
speech[] = { "\Sound\hello1.ogg" }; // sound file path relative to mission or campaign directory
class Arguments {}; // unused here
};
class hi_how_are_you
{
text = "Hi, how are you?";
speech[] = { "\Sound\hi_how_are_you.ogg" };
class Arguments {};
};
class good_you
{
text = "$STR_GoodYou"; // has to start with "STR_"!
speech[] = { "\Sound\good_you.ogg" };
class Arguments {};
};
class fine_thanks
{
text = "$STR_FineThanks";
speech[] = { "\Sound\fine_thanks" }; // no extension means .wss to the engine
class Arguments {};
};
// these sentences are here to be a full example for later Conversation Event Handler example
class what_do_we_do { text = "What do we do today?"; speech[] = { "\Sound\wdwd.ogg" }; class Arguments {}; };
class choose_football { text = "Let's football!"; speech[] = { "\Sound\cf.ogg" }; class Arguments {}; };
class choose_bike { text = "Let's bike?"; speech[] = { "\Sound\cb.ogg" }; class Arguments {}; };
class choose_arma2 { text = "I know! Arma 2"; speech[] = { "\Sound\ca.ogg" }; class Arguments {}; };
// the Interrupted sentence triggered when the conversation menu is closed without answering (e.g using backspace)
class Interrupted
{
text = "Hey, come back!";
speech[] = { "\Sound\interrupted.ogg" };
class Arguments {};
};
};
// Needed parameters.
class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };
.bikb Advanced Example
See Words configuration and below for more details.
class Sentences
{
class AirstrikeRequest
{
// %team and %location will be replaced by the game engine with according values
text = "%team requesting close air support at grid %location ";
// available words are defined in config > RadioProtocol > Words
speech[] = { %Team, RequestingCloseAirSupportAtGrid, %Location };
class Arguments
{
class Team { type = "simple"; }; // refers to %Team, first element of speech[]
// "RequestingCloseAirSupportAtGrid" is part of Radio Protocol
class Location { type = "simple"; }; // refers to %Location, last element of speech[]
};
};
};
class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };
Above sentence would be used this way:
.bikb BIS_fnc_kbTell Example
BIS_fnc_kbTell needs a Description.ext CfgSentences entry presented as follows:
class CfgSentences
{
class MissionName
{
class Event1
{
file = "kb\event1.bikb"; // mandatory
class Sentences
{
class Sentence1
{
// the following arguments are used by BIS_fnc_kbTell (if they are defined, they are not mandatory)
actor = "obi1"; // (missionNamespace getVariable actor) speaker variable name (can NOT be "player")
variant = ""; // used by BIS_fnc_kbTell to define an alternative sentence
variantText = ""; // used by BIS_fnc_kbTell to define an alternative sentence
};
class Sentence2
{
actor = "griev";
};
class Sentence3
{
actor = "griev";
};
};
};
};
};
with a .bikb file looking like this:
class Sentences
{
class Sentence1
{
text = "$STR_HelloThere";
speech[] = { "\Sound\hello.ogg" };
class Arguments {};
};
class Sentence2
{
text = "$STR_GeneralKenobi";
speech[] = { "Sound\gk.ogg" };
class Arguments {};
};
class Sentence3
{
text = "$STR_YouAreABoldOne";
speech[] = { "Sound\bold.ogg" };
class Arguments {};
};
};
class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };
A tidier way of doing so is to put all the needed information in the .bikb file:
class Sentences
{
class Sentence1
{
text = "$STR_HelloThere";
speech[] = { "\Sound\hello.ogg" };
class Arguments {};
actor = "obi1";
};
class Sentence2
{
text = "$STR_GeneralKenobi";
speech[] = { "Sound\gk.ogg" };
class Arguments {};
actor = "griev";
};
class Sentence3
{
text = "$STR_YouAreABoldOne";
speech[] = { "Sound\bold.ogg" };
class Arguments {};
actor = "griev";
};
};
class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };
And to include it via #include
in Description.ext:
class CfgSentences
{
class MissionName
{
class Event1
{
file = "kb\event1.bikb";
#include "kb\event1.bikb" // avoids a double declaration
};
};
};
Et voilà ! All that remains to be done now is to call the discussion like this: ["Event1", "MissionName"] call BIS_fnc_kbTell; // note that the topic comes first;
the game will make the defined actors say the lines in the order they were declared. BIS_fnc_kbTell will manage to use kbAddTopic, kbTell and other commands.
Conversation FSM
As stated earlier, the Conversation FSM fires on sentences received by an AI and defines an AI unit's reaction. The Conversation FSM receives the following arguments:
- _this: Object - receiver or listener of the sentence. One of the units that had this particular script assigned via kbAddTopic
- _from: Object - the unit that told the sentence
- _sentenceId: String - the sentence this unit is reacting to. Defined in .bikb in class Sentences
- _topic: String - topic name used in kbAddTopic
See also: FSM, FSM Editor
Conversation FSM Example
Conversation Event Handler
The Conversation Event Handler is code, provided through kbAddTopic, that is executed with each sentence received by a player, and will constantly fire (onEachFrame) when the player is pointing at a "talkable" person at "talkable" range. Following parameters are passed:
- _this: Object - the player receiving the sentence. Must have had this particular script assigned via kbAddTopic
- _from: Object - the unit that told the sentence
- _sentenceId: String - the sentence the player is reacting to. Defined in .bikb in class Sentences
- _topic: String - topic name used in kbAddTopic
Its return value is used to provide the player's available replies; its format is an Array of arrays (or an empty array) that can look like this:
There is a certain resemblance with the kbTell syntax; note that the forceRadio parameter is not present.
Conversation Event Handler Example