Table of Contents

ArmA 2 Conversation System

ArmA 2 Forum, ArmA 2 Home, ArmA 2 Config, ArmA 2 File Formats, ArmA 2 Missions, ArmA 2 3D Modeling, ArmA 2 Scripting, ArmA 2 Terrain, ArmA 2 Texturing, ArmA 2 Tools

As many of you have noticed, ArmA 2 introduced a new conversation system (I'll be referring to it as “conversations” further on) which replaced the old say/…Radio description.ext-based approach. There have been many questions regarding this subject, so I decided to write a short overview of the possibilities and usage of this system.

Theory

In order to run a conversation, all of the participants need to have the proper topic added to them. The conversation then starts with the first sentence which one of the participants says to another. After that, the conversation flow is usually controlled by scripts - FSM's and event handlers assigned to the participants. After a participant receives a sentence, his script reacts to its ID and reacts with the proper answer. It may sound a bit complicated, but it's really not.

Let's start with adding the topic. The scripting command to do this is kbAddTopic:

person kbAddTopic [topicName, fileName.bikb, (fileName.fsm, (eventHandler))]

topicName: (string) Can be anything.
fileName.bikb: (string) Name of the .bikb file - will be described later.
fileName.fsm: (string) Name of the .fsm file - will be described later. Optional.
eventHandler: (string or code) Will be described later. Optional.

Here is an example of what the code usually looks like:

unit2 kbAddTopic ["baseDefended", "baseDefended.bikb", "baseDefended_unit2.fsm", {call compile preprocessFileLineNumbers "baseDefended_unit2.sqf"}]

.bikb files

Stand for “Bohemia Interactive Knowledge Base” as it was originally used only for storing an AI unit's memory of what it has seen. Not important to you. You will use these files to store all the speech samples (referred to as “Sentences” further on) used for the topic. This is in fact quite similar to the good old cfgSounds and cfgRadio classes in description.ext. Here is a short .bikb file:

class Sentences
{
 
	class example_01
	{
		text = "Hello Bret.";
		speech[] = {"Sound\jemaine01.ogg"};
		class Arguments {};
 
	};
 
	class example_02
	{
		text = "Oh, hello Jemaine.";
		speech[] = {"Sound\bret01.ogg"};
		class Arguments {};
 
	}
};
class Arguments{};
class Special{};
startWithVocal[] = {hour};
startWithConsonant[] = {europe, university}

text: Subtitles used to caption the sample. If you're using stringtable, use $stringName (has to start with “STR_”!) speech: Sound sample.

arguments, special, startWithVocal, startWithConsonant: Don't worry about these.

Scripts

In both FSM's and event handlers, there are some default variables which you'll be using quite often:
_this: Receiver of the sentence. The unit that had this particular script assigned via kbAddTopic.
_from: Self-explanatory. Basically the unit that told be the sentence.
_sentenceId: The sentence this unit is reacting to. Defined in .bikb in class Sentences.
_topic: Self-explanatory. Topic name used in kbAddTopic.

FSM

FSM stands for Finite-state machine. We have released the FSM Editor some time ago. I will not describe its functionality here, I'm sure there are plenty tutorials out there. Here I'll just show you an example FSM used for a simple conversation (you need to have the FSM Editor installed to open it).

As you can see, the FSM parameter is optional in kbAddTopic. That is because a) you don't want to use scripts at all and rather manage the conversation manually (about that later) or b) the unit is always controlled by a player. The engine recognizes who's controlling the unit by the time it receives a sentence. If it's controlled by AI, the assigned FSM is executed. If it's player-controlled, it fires the event handler. If you're making an MP mission and the unit is playable, you will want to use both the FSM and the event handler.

Event Handlers

Nothing to do with our standard event handlers. This is a code used only if the unit is controlled by a player and is executed not only if it receives a sentence, but also if the player points at someone and is close enough to start a conversation (“Talk to” action appears). This is very important to understand. FSM's are executed only once after each received sentence, event handlers are fired constantly (usually every frame) as long as you're pointing at somebody.

Here is an example showing all you might want to use (you should get familiar with kbTell and kbWasSaid first):

// here we'll be storing all the sentences from which the player will choose (the menu on the left side of the screen)
// if there's only one option in the array, you will have the sentence as the "Talk to" action
 
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 I'm pointing at my buddy
// if I'm not answering any of his sentences
// if I haven'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
// I use switch-case-do, it's 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": {
		// here the player will have 3 answers to choose from
		BIS_convMenu = BIS_convMenu + [["Football.", _topic, "choose_footbal", []]];
		BIS_convMenu = BIS_convMenu + [["Bike.", _topic, "choose_bike", []]];
		BIS_convMenu = BIS_convMenu + [["Arma II.", _topic, "choose_arma2", []]]
	};
};
 
// return the sentence list pool
BIS_convMenu

There. Everything should be explained in the comments inside the code. As you can see, it's nothing more than a compiled sqf function.