Conversations: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Fix paragraphs and example)
m (Usage refactor)
Line 14: Line 14:


== Usage ==
== Usage ==
* a [[#Conversation FSM|Conversation FSM]] will only fire when an AI "receives" a sentence, and make it react accordingly
* A '''topic''' is defined in a '''.bikb''' file listing all available sentences in the topic
* a [[#Conversation Event Handler|Conversation Event Handler]] fire when the [[player]] "receives" a sentence, and will also constantly fire ([[onEachFrame]]) as long as the player is pointing at somebody at discussion range
* A topic must be added to the concerned units, with eventually an '''[[#Conversation FSM|Conversation FSM]]''' and/or a '''[[#Conversation Event Handler|Conversation Event Handler]]'''
* in the case of a playable unit (that can be either a player or an AI), both should be present to ensure a proper reaction in every encounter scenario
* 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 [[switchableUnits|playable]] (can be either player or AI) both should be present to ensure a proper reaction in every encountered scenario.




Line 25: Line 27:
# once the unit said wanted sentences (checked ''via'' [[kbWasSaid]]),
# once the unit said wanted sentences (checked ''via'' [[kbWasSaid]]),
# the topic can be removed (''via'' [[kbRemoveTopic]]).
# the topic can be removed (''via'' [[kbRemoveTopic]]).
* Related commands are listed in [[:Category:Command Group: Conversations|Conversations Command Group]].
* Related functions are listed in [[:Category:Function Group: Conversations|Conversations Function Group]].




Line 90: Line 97:
class choose_arma2 { text = "I know! Arma 2"; speech[] = { "\Sound\ca.ogg" }; class Arguments {}; };
class choose_arma2 { text = "I know! Arma 2"; speech[] = { "\Sound\ca.ogg" }; class Arguments {}; };


// the Interrupted sentence is triggered when the conversation menu is closed without answering (e.g using backspace)
// the Interrupted sentence triggered when the conversation menu is closed without answering (e.g using backspace)
class Interrupted
class Interrupted
{
{
Line 147: Line 154:
== Conversation Event Handler ==
== Conversation Event Handler ==
The '''Conversation Event Handler''' is '''not''' an [[:Category:Event_Handlers|Event Handler]] as we know them.
The '''Conversation Event Handler''' is '''not''' an [[:Category:Event_Handlers|Event Handler]] as we know them.
This is a [[code]] that will be executed with each sentence '''received by a player''' as well as when the player is pointing at a "talkable" person. Following parameters are passed:
It is [[Code]] that will be 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

Revision as of 17:47, 28 March 2018

Logo A2.png1.00


Introduction

Conversations are a system introduced with Arma 2 and created to enhance discussions. 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 in a .bikb file listing all available sentences in the topic
  • A topic must be added to the concerned units, with eventually an 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

  1. must be added to units (via kbAddTopic)
  2. for the units to be able use it (via kbTell for example)
  3. once the unit said wanted sentences (checked via kbWasSaid),
  4. the topic can be removed (via kbRemoveTopic).



Manual conversation example

miles   kbAddTopic ["briefing", "kb\briefing.bikb"];
shaftoe kbAddTopic ["briefing", "kb\briefing.bikb"];

shaftoe kbTell [miles, "briefing", "shaftoe_briefing_H_1"];
waitUntil { shaftoe kbWasSaid [miles, "briefing", "shaftoe_briefing_H_1", 3]; };

miles kbTell [shaftoe, "briefing", "shaftoe_briefing_M_1"];
waitUntil { miles kbWasSaid [shaftoe, "briefing", "shaftoe_briefing_M_1", 3]; };

hint "Conversation ended.";
// you could use kbRemoveTopic here to "clear" the units if the topic is not required anymore. This is not mandatory.


Conversation .bikb file

.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).

Sounds don't need to be defined in CfgSounds or CfgRadio unless you want to use them with e.g playSound, say or groupRadio.

In Arma 3, using a .lip file for a sound file (.ogg or .wss) creates a glitch making the sound being said about 20× faster. Normal conversations can't be made with say properly anymore, where this new conversation system will automatically use setRandomLip during the speech, avoiding the use of a corresponding .lip file.
TLDR: you don't need .lip files anymore.


"Interrupted" event

The left-side conversation menu (with the list of possible sentences) can be closed via backspace at all times. If you want to handle this event as well, you have to add new sentence class called Interrupted into your .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
		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.ogg" };
		class Arguments {};
	};

	// these sentences are here to be a full example for later Conversation Event Handler example
	class what_do_we_do_today { text = "What do we do today?"; speech[] = { "\Sound\wdwdt.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 {};
	};
};

// Don't worry about these.
class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };


.bikb advanced example

See Words configuration and below for more details.

class Sentences
{
	class AirstrikeRequest 
	{
		text = "%team requesting close air support at grid %location ";
		speech[] = { %Team, RequestingCloseAirSupportAtGrid, %Location }; // words are defined in Cfg/RadioProtocol/Words
		class Arguments 
		{
			class Team { type = "simple"; };
			class Location { type = "simple"; };
		};
	};
};

class Arguments {};
class Special {};
startWithVocal[] = { hour };
startWithConsonant[] = { europe, university };


Conversation FSM

As stated earlier, the Conversation FSM fires only when an AI "receives" a sentence and defines its 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

Template:note


Conversation Event Handler

The Conversation Event Handler is not an Event Handler as we know them. It is Code that will be 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 this unit is reacting to. Defined in .bikb in class Sentences
  • _topic: String - topic name used in kbAddTopic


Conversation Event Handler example

// here we will be storing all the sentences from which the player will choose (the menu on the left side of the screen)
// if there is only one option in the array, the sentence will replace the "Talk to" action name

 BIS_convMenu = [];

// we want the player to be able to approach his buddy and talk to him via the action menu.
// we need to check:
// if the player is pointing at his buddy
// if the player is not answering any of his buddy's sentences
// if the player hasn't told him hello already
// then we add that array to BIS_convMenu - the parameters are mostly self-explanatory:

if (_from == buddy1 && _sentenceId == "" && !(_this kbWasSaid [_from, _topic, "hello1", 999999])) then
{
	BIS_convMenu = BIS_convMenu + [["Say hello.", _topic, "hello1", []]];
};

// here we make the unit say the proper sentence based on the one he just received
// switch-case-do is used here but it is completely up to you how to evaluate it (if-then etc.)
switch (_sentenceId) do
{
	case "hello1":
	{
		_this kbTell [_from, _topic, "hi_how_are_you"];
	};
	case "good_you":
	{
		_this kbTell [_from, _topic, "fine_thanks"];
	};
	case "what_do_we_do_today": {
		// the player will have 3 answers to choose from:
		BIS_convMenu = BIS_convMenu + [["Football.", _topic, "choose_football", []]];
		BIS_convMenu = BIS_convMenu + [["Bike.", _topic, "choose_bike", []]];
		BIS_convMenu = BIS_convMenu + [["Arma II.", _topic, "choose_arma2", []]]
	};
};

// return the sentence list pool
BIS_convMenu;


See also