Jump to content
IndeedPete

Spin-Off Release: Simple Conversation System

Recommended Posts

Thank you. True, I could handle it with a kiled EH or an alive condition in the action itself. A one-time-only condition could be done as well. Maybe not even with additional parameters but dynamic variables, I'll do some research. Multiple yet random lines can already be achieved with the workaround in my last post but I see you're aiming for a different functionality there. For now it could also be done by having several conversations (topics) with the same first sentence but different conditions - the player won't even know the topic changed yet the responses are different. I'll work on it and hope to upload a new version soon, there have been some more changes in the past few days.

Share this post


Link to post
Share on other sites

Thx for this script IndeePete.

But i have problems to add revive scripts (AiS) and other scripts that needs cfg functions. I add them to the description but when i start the mission i get ctd because cfg functions is already defiend.

Srry for the noob question but dont check how to implement more scripts that needs cfg funtions, and add something to the init after your conversation, because all after the conversation after the init wont load in game.

Mayby someone can help me.

Here is my descrption :

#include "cfg\defines.hpp"

#include "missionConversations.hpp"

#include "cfg\functions.hpp"

#include "cfg\conv\dialogs.hpp"

author = "Dr.Speedy G.";

OnLoadName = "First Contract";

respawn = BASE;

respawndelay = 10;

disabledAI = true;

enableDebugConsole = 2;

//--------------------------------------------------------------

//------------------------AIS INJURY----------------------------

//--------------------------------------------------------------

class RscTitles {

#include "ais_injury\dialogs\rscTitlesAIS.hpp"

};

class CfgFunctions {

#include "ais_injury\cfgFunctionsAIS.hpp"

};

//--------------------------------------------------------------

And here is my Init:

// Buddy Setup

IP_Buddy setVariable ["IP_LiveFeed", true];

IP_Buddy setVariable ["IP_Avatar", "img\buddyAvatar.jpg"];

[iP_Buddy, "opener"] call IP_fnc_addConversation;

_nul = [] spawn {

waitUntil {time > 0};

[iP_Buddy, "Meet me at the beachhouse NORTH EAST from SHAMALI", "SIDE"] call IP_fnc_simpleSentence;

};

tf_no_auto_long_range_radio = true;

[] execVM "VCOMAI\init.sqf";

player setVariable ["FiredTime", 0];

player addEventHandler ["Fired",{null = [_this] call FiredAtTarget;}];

// TcB AIS Wounding System -----------------------------------------------------------------------------------------

if (!isDedicated) then {

TCB_AIS_PATH = "ais_injury\";

{[_x] call compile preprocessFile (TCB_AIS_PATH+"init_ais.sqf")} forEach (if (isMultiplayer) then {playableUnits} else {switchableUnits}); // execute for every playable unit

//{[_x] call compile preprocessFile (TCB_AIS_PATH+"init_ais.sqf")} forEach (units group player); // only own group - you cant help strange group members

//{[_x] call compile preprocessFile (TCB_AIS_PATH+"init_ais.sqf")} forEach [p1,p2,p3,p4,p5]; // only some defined units

};

Share this post


Link to post
Share on other sites

I see your problem, someone would eventually run into it by using other scripts with CfgFunctions. One option for you would be to merge the two configs ("ais_injury\cfgFunctionsAIS.hpp" and "cfg\functions.hpp") and leave only one #inlcude in your description.ext. So it would look like:

class CfgFunctions
{
// Here goes the content of the "ais_injury\cfgFunctionsAIS.hpp" but WITHOUT the "class CfgFunctions" and the matching "};" at the end! 

       class IP
{
	class conv
	{
		class addConversation
		{
			file = "fnc\conv\addConversation.sqf";
		};
		class closeConversation
		{
			file = "fnc\conv\closeConversation.sqf";
		};
		class openConversation
		{
			file = "fnc\conv\openConversation.sqf";
		};
		class removeConversation
		{
			file = "fnc\conv\removeConversation.sqf";
		};
		class selectResponse
		{
			file = "fnc\conv\selectResponse.sqf";
		};
		class simpleSentence
		{
			file = "fnc\conv\simpleSentence.sqf";
		};
	};
};
};

If you only use the simpleSentence another option would be to just compile this function for your needs. Leave out the #include "cfg\functions.hpp" in your description and put in your init:

IP_fnc_simpleSentence = compile(preprocessFileLineNumbers "fnc\conv\simpleSentence.sqf");

I'm not sure if I understand your last question. Maybe you should provide more details or failed code on what you want to achieve.

Share this post


Link to post
Share on other sites

Hey guys,

Just wondering if there is a way to regulate how long a simpleSentence is displayed for? I've got an initial intro happening where the simpleSentences are fired by individual scripts (haven't been able to get them to work with sleep commands in a single script).. But I'm finding the last display of text appears and disappears within maybe 2 seconds. Which isn't enough time to really read the sentence. Is there a way I can choose how long each is displayed for before another one interupts it? Or am I approaching the entire thing wrong with individual scripts for each simpleSentence being fired via triggers?

Share this post


Link to post
Share on other sites

Hey, thanks for your post! It seems like I forgot to add the function's documentation / header to my original post - it's fixed now. As for your question: If you want to simulate a conversation made of several sentences (function calls) I'd recommend to write a script file.

For example "myConv.sqf":

[iP_Main, "Ha, I can see land! Is this Greece already?!", "DIRECT"] call IP_fnc_simpleSentence;
[iP_Refugee1, "I'm not sure, I don't think so! Hey Nikos, is this Greece over there?!", "DIRECT"] call IP_fnc_simpleSentence;
[iP_Trafficker, "No, my friends, not yet! We're just stopping on this island to get you some new passports! So you can cross the border to enter the European Federation!", "DIRECT"] call IP_fnc_simpleSentence;

And then run it from a trigger with:

nul = [] execVM "myConv.sqf";

To display single sentences longer you can use the additional parameters documented in the function header:

/*
Name: simpleSentence
Author: IndeedPete
Purpose: Simulate radio or direct conversations between units. Calculates delay based on input length.
----------
Parameters:
_speaker - OBJECT: Unit that should say the _sentence. - player
_sentence - STRING: Text that the _speaker should say. - "Hello world!"
_wichChat - STRING (OPTIONAL): Which way of communication should be used. Available chats: "SIDE", "GROUP", "VEHICLE", "CUT" or "DIRECT" - "DIRECT" - DEFAULT: "SIDE"
_add - NUMBER (OPTIONAL): Addition in seconds to the calculated delay. Can be negative. - 5 - DEFAULT: 0
_len - NUMBER (OPTIONAL): Fixed delay. - 20 - DEFAULT: ((count (toArray _sentence)) * _x) <- calculation to determine delay
----------
Requires:
Dialog "IP_DLG_SIMPLESENTENCE"
.jpg - "img\defaultAvatar.jpg"
*/

So to make a short sentence display longer or a long sentence shorter do (examples):

[player, "Damn!", "DIRECT", [b][color="#FF0000"]2[/color][/b]] call IP_fnc_simpleSentence; // Will be displayed for 2 seconds more.

[player, ""No, my friends, not yet! We're just stopping on this island to get you some new passports! So you can cross the border to enter the European Federation!", "DIRECT", [b][color="#FF0000"]-1[/color][/b]] call IP_fnc_simpleSentence; // Will be displayed for 1 second less.

[player, "Damn!", "DIRECT", [b][color="#FF0000"]0, 3[/color][/b]] call IP_fnc_simpleSentence; // Fixed length -  will be displayed for exactly 3 seconds.

Share this post


Link to post
Share on other sites

I would like to run Random Roadside IED along with this script. However, I amn having problems combining both functions in the description.exe. My game keeps crashing telling me that the cfg func is already defined, just like the post above. I tried what was written above but that did not help. This line is for the IED: #include "EPD\EPDcfgFunctions.hpp". And I also have another script for VAS and Explosives. For the explosives, I am to add this to the description.exe

class RONIN

{

#include "RONIN\rExplosivesAttachTo\cfgfunctions_eAto.hpp"

#include "RONIN\rObjectManipulation\cfgFunctions_objManipulate.hpp"

};

And this for Vas:

#include "VAS\menu.hpp"

class CfgFunctions

{

//VAS

#include "VAS\cfgfunctions.hpp"

How do i make this work?

Share this post


Link to post
Share on other sites

Hi there! You've got to have just one CfgFunctions otherwise the game crashes. Best option in your case would be to habe just one Definition oft CfgFunctions in your description and then include the external scripts AS sub-categories.

Share this post


Link to post
Share on other sites

Glad to hear from you, Pete!

I do not fully understand what you said above.

Here is the example of my failed description.exe

//Satcom

#include "pxs_satcom_a3\init_interface.hpp"

//IndeedPete Conversation

#include "cfg\functions.hpp"

#include "cfg\defines.hpp"

#include "cfg\conv\dialogs.hpp"

class CfgFunctions

{

//Randomly generated roadside IED's

#include "EPD\EPDcfgFunctions.hpp"

//JTAC Engineer

class RONIN

{

#include "RONIN\rExplosivesAttachTo\cfgfunctions_eAto.hpp"

#include "RONIN\rObjectManipulation\cfgFunctions_objManipulate.hpp"

};

};

And here is a picture of my mission folder

https://www.dropbox.com/s/dc4wpfah3mvsavo/Screenshot%20%282%29.png

Here is my mission folder so that you can see everything easily

https://www.dropbox.com/s/m6qo59mgva4imgj/Tier1.pja307.7z

In which folder do I put the other functions into?

---------- Post added at 16:59 ---------- Previous post was at 15:37 ----------

I was able to figure it out (but I had to sacrifice the Satcom script) First, I only wanted the basic simple sentences, not the full conversation system. So, in the Description, I commented out

//#include "cfg\functions.hpp". In my init, I did as Pete said to do above by adding this to it: IP_fnc_simpleSentence = compile(preprocessFileLineNumbers "fnc\conv\simpleSentence.sqf");

Now, everything works.

Pete, I would still like to know how to add other functions into a sub folder within another function without having to remove another script. If you do not mind and have the time, please help me out. Thanks.

Edited by chondo999

Share this post


Link to post
Share on other sites

Glad you made it! I'd be happy to provide you with a good example as it's actually not that complicated. But I'm typing with my phone right now from some coffee bar in south-eastern Europe. I should be back at my desk by wednesday if it's not urgent.^^

Share this post


Link to post
Share on other sites

Thanks man. I need to learn patience anyways. lol. Wednesday it is. Thank, you.

In case you need it, here are the links to the scripts I am trying to use:

SATCOM

http://www.armaholic.com/page.php?id=25816

IED

http://www.armaholic.com/page.php?id=23995

EXPLOSIVES

http://www.armaholic.com/page.php?id=25868

VAS

http://www.armaholic.com/page.php?id=25859

And Yours

Edited by chondo999

Share this post


Link to post
Share on other sites

I'm back. It's rather easy if you understood how configs work in Arma 3. One thing right at the beginning: You can have a config one time and one time only defined in your mission. That's your problem, you've defined CfgFunctions several times and the game crashes because it can't combine or distinguish those. CfgFunctions looks - like the wiki says - like this:

class CfgFunctions
{
class Tag
{
	class Category
	{
		class function
		{
			file = "myFunction.sqf";
		};
	};
};
};

And the functions.hpp for my conv system you're including with #include to your mission looks like this:

class CfgFunctions
{
class IP
{
	class conv
	{
		class addConversation
		{
			file = "fnc\conv\addConversation.sqf";
		};
		class closeConversation
		{
			file = "fnc\conv\closeConversation.sqf";
		};
		class openConversation
		{
			file = "fnc\conv\openConversation.sqf";
		};
		class removeConversation
		{
			file = "fnc\conv\removeConversation.sqf";
		};
		class selectResponse
		{
			file = "fnc\conv\selectResponse.sqf";
		};
		class simpleSentence
		{
			file = "fnc\conv\simpleSentence.sqf";
		};
	};
};
};

Now, as said, you're probably including this stuff multiple times (for every script package you use). The game now sees multiple CfgFunctions and crashes. You could bypass this by just pasting all different CfgFunctions from all script packages together. So, for my conv system you could replace the

#include "cfg\functions.hpp"

in your description.ext with

class CfgFunctions
{
class IP
{
	class conv
	{
		class addConversation
		{
			file = "fnc\conv\addConversation.sqf";
		};
		class closeConversation
		{
			file = "fnc\conv\closeConversation.sqf";
		};
		class openConversation
		{
			file = "fnc\conv\openConversation.sqf";
		};
		class removeConversation
		{
			file = "fnc\conv\removeConversation.sqf";
		};
		class selectResponse
		{
			file = "fnc\conv\selectResponse.sqf";
		};
		class simpleSentence
		{
			file = "fnc\conv\simpleSentence.sqf";
		};
	};
};

class SecondFunctionPackage
{
	class bla
	{
	...
};

Another approach would be to modify the cfg\functions.hpp, i.e. removing the CfgFunctions shell from it:

class IP
{
class conv
{
	class addConversation
	{
		file = "fnc\conv\addConversation.sqf";
	};
	class closeConversation
	{
		file = "fnc\conv\closeConversation.sqf";
	};
	class openConversation
	{
		file = "fnc\conv\openConversation.sqf";
	};
	class removeConversation
	{
		file = "fnc\conv\removeConversation.sqf";
	};
	class selectResponse
	{
		file = "fnc\conv\selectResponse.sqf";
	};
	class simpleSentence
	{
		file = "fnc\conv\simpleSentence.sqf";
	};
};
};

And then your description could look like:

class CfgFunctions
{
#include "cfg\functions.hpp"
#include "otherPackage\functions.hpp"
...
};

Third way would be what you did - leaving CfgFunctions out at all and compile the functions on init. However, you must be careful with this because, e.g. you won't be able to run the function from a unit's init line because init lines are executed prior to init.sqf means the game doesn't know the function until mission start.

I'm really tired right now so I might wrote totally confusing stuff. Please let me know if it helped.^^

Share this post


Link to post
Share on other sites

In the dialog file (defines.hpp) you are using the base class names instead of your own. This causes conflict with other scripts doing the same thing. Please update :)

Share this post


Link to post
Share on other sites

I see, thanks for the heads-up, I used the standard defines from Iceman. I'll see what I can do, have to do an update anyway.

Share this post


Link to post
Share on other sites

So, I brought an update on the way which contains some new stuff, should fix that dialog defines interference stuff and is easier to deploy. As usual, this is just a minimally adapted cutout of the M.E.R.C.S. project. Check the extended examples, the example mission and the function headers for details. Enjoy!

Setup

  1. Download v1.04 example mission.
  2. Copy conv folder to your mission.
  3. Create description.ext and add:
    #include "conv\cfg\defines.hpp"
    #include "conv\cfg\dialogs.hpp"
    
    class CfgFunctions
    {
    #include "conv\cfg\functions.hpp"
    };


  4. (Optional) Create "missionConversations.hpp", fill it with conversations and add to your desciption.ext:
    #include "missionConversations.hpp"

    .

  5. (Optional) Set "IP_Avatar", "IP_LiveFeed" and "IP_ConvSpecial" variables on units.

The "missionConversations.hpp"

is the central config file you need in order to create full multiple choice conversations. In its current state it should look like this:

class Conversations // main config class - DO NOT change the name!
{
class MyFirstConversation // Name of the conversation.
{
               arguments[] = {"(name player)"}; // Arguments passed to each sentence. Can be used via %1, %2, etc.
	condition = ""; // Condition (Boolean) which causes the conversation to show up as action or response in MC. Empty string means conversation will always show up.
	expression = "hint 'Sucess, yay!';"; // Expression(s) that is/are called after dialog is created and filled. Passed arguments are: [first speaker, second speaker, conversation].
	responses[] = {"MyFirstResponse", "exit"}; // Possible responses to this conversation. Must be classname(s) of another conversation(s) in this config.
	sentences[] = {"Hello, I'm %1!", "Cool, I'm Mike, nice to meet you!"}; // Sentences of this conversation. Every even sentence will be said by the first person, every odd by the second. The first sentence of the conversation marks the response / action name in other conversations.
};
       class MyFirstResponse // Name of the conversation.
{
	responses[] = {"exit"};
	sentences[] = {"How are you?", "Fine, fine."};
};
       class exit
{
	expression = "call IP_fnc_closeConversation; nul = [iP_Buddy, 'See ya!', 'DIRECT', 3] spawn IP_fnc_simpleSentence;";
	sentences[] = {"Good bye!"};
};
};

The Variables

There are currently two variables that can be set on units by:

unit setVariable ["VarName", value];

  • "IP_LiveFeed" - True: shows live cam when saying simpleSentence and not in a vehicle. - False: Shows avatar always.
  • "IP_Avatar" - Path to avatar picture, should be roughly 4:3 format. Default avatar picture is used if variable is nil.
  • "IP_ConvSpecial" - Will show user defined text below the avatar in a conversation.

The Functions

This system is based on functions defined via CfgFunctions. Below are the header of all current functions. Check them for parameter explanation.

/*
Name: addConversation
Author: IndeedPete
Purpose: Adds conversation from config to unit or object related to unit (e.g. a cellphone), i.e. adds action to start the conversation.
----------
Parameters:
_unit - OBJECT: Unit that the action should be attached to. - MyInterestingConversationPartner
_conversation - STRING: The config entry referring to the desired conversation. - "MyFirstConversation"
_object - OBJECT (Optional): Action will be attached to given object instead of unit. - MyCellphone - DEFAULT: objNull
*/

/*
Name: closeConversation
Author: IndeedPete
Purpose: Closes current conversation, i.e. the dialog. Is in fact just a place holder right now. 
*/

/*
Name: openConversation
Author: IndeedPete
Purpose: Opens a conversation (dialog) from config.
----------
Parameters:
_first - OBJECT: The first conversation participant saying every EVEN sentence. - player
_second - OBJECT: The second conversation participant saying every ODD sentence.  - MyInterestingConversationPartner
_conversation - STRING: The config entry referring to the desired conversation. - "MyFirstConversation"
----------
Requires:
Dialog "IP_DLG_CONVERSATION"
.jpg - "conv\img\defaultAvatar.jpg"
*/

/*
Name: removeConversation
Author: IndeedPete
Purpose: Removes conversation from unit or object, i.e. removes action to start the conversation.
----------
Parameters:
_unit - OBJECT: Unit that the action should be removed from. - MyInterestingConversationPartner
_conversation - STRING: The config entry referring to the desired conversation. - "MyFirstConversation"
*/

/*
Name: selectResponse
Author: IndeedPete
Purpose: Upon response selection, conversation dialog is closed and reopened to show the new conversation based on the selected response.
----------
Parameters:
_this - STRING: Data string which contains the two conversation participants and the response name. Trick to bypass engine limitation in passing additional arguments via dialog EHs. - "['IP_Main', 'IP_Buddy', 'MyFirstConversation']"
*/

/*
Name: simpleConversation
Author: IndeedPete
Purpose: Wrapper function to create a simple conversation from several simple sentences (IP_fnc_simpleSentence).
----------
Parameters:
_speakers - ARRAY OF OBJECTS: Units that alternately say the _sentences. - [player, SomeGuy]
_sentences - ARAAY OF STRINGS: Sentences the _speakers should say. Every Xth sentence will be spoken by the Xth speaker. - ["Hello world!", "Fuck off!"]
_wichChat - STRING (OPTIONAL): Which way of communication should be used. Available chats: "SIDE", "GROUP", "VEHICLE", "CUT" or "DIRECT" - "DIRECT" - DEFAULT: "SIDE"
_isCutscene - BOOL (OPTIONAL): Cutscene mode: If set to true cinema borders will show up and the conversation can be skipped by the player pressing space. - true - DEFAULT: false
----------
Requires:
IP_fnc_simpleSentence
*/

/*
Name: simpleSentence
Author: IndeedPete
Purpose: Simulate radio or direct conversations between units. Calculates delay based on input length. Defines global variable "IP_SimpleSentence_Talking" while someone is talking.
----------
Parameters:
_speaker - OBJECT: Unit that should say the _sentence. - player
_sentence - STRING: Text that the _speaker should say. - "Hello world!"
_wichChat - STRING (OPTIONAL): Which way of communication should be used. Available chats: "SIDE", "GROUP", "VEHICLE", "CUT" or "DIRECT" - "DIRECT" - DEFAULT: "SIDE"
_add - NUMBER (OPTIONAL): Addition in seconds to the calculated delay. Can be negative. - 5 - DEFAULT: 0
_len - NUMBER (OPTIONAL): Fixed delay. - 20 - DEFAULT: ((count (toArray _sentence)) * _x) <- calculation to determine delay
----------
Requires:
Dialog "IP_DLG_SIMPLESENTENCE"
.jpg - "conv\img\defaultAvatar.jpg"
*/

Examples

Setting up a unit and add a conversation (action) to it:

IP_Buddy setVariable ["IP_LiveFeed", true];
IP_Buddy setVariable ["IP_Avatar", "img\buddyAvatar.jpg"];
[iP_Buddy, "opener"] call IP_fnc_addConversation;

Open conversation from script:

nul = [player, IP_Buddy, "MyFirstConversation"] spawn IP_fnc_openConversation;

Creating simple radio sentence from script:

nul = [iP_Buddy, "Hey, come over here if you want to ask me some questions!", "SIDE"] spawn IP_fnc_simpleSentence;

Creating a small in-game cutscene:

[
	[iP_Commander, player],
	[
		"Hey, I just met you!",
		"And this is crazy!",
		"So here's my number!",
		"Call me maybe!"
	],
	"DIRECT",
	true
] call IP_fnc_simpleConversation;	

Changelog

v1.04 - Added IP_fnc_simpleConversation. Changed folder structure. Changed defines to not interfere with other script packages. Added / changed some minor stuff.

Download v1.04

Share this post


Link to post
Share on other sites
I see, thanks for the heads-up, I used the standard defines from Iceman. I'll see what I can do, have to do an update anyway.

But I realise this might be a consequens on how dialogs are created in the game? I.e the other scripts file is essentially identical. Could it be that the mission needs one global define file for everything?

Share this post


Link to post
Share on other sites

I'm honestly not a master when it comes to dialogs. What I did was replacing the generic "RscSomething" with "IP_RscSomething" and then adapting my dialogs to base on the modified class names. I've got no idea if that actually works but it doesn't rely on those generics anymore. In my logic that means another scripter could just define "OtherScripter_RscSomething" and there would be two different versions of a textfield or frame or whatever. But that's just a hypothesis. On the other hand I had to do an update anyway, so I finally got that done.^^

Share this post


Link to post
Share on other sites

New version frontpaged on the Armaholic homepage.

================================================

We have also "connected" these pages to your account on Armaholic.

This means in the future you will be able to maintain these pages yourself if you wish to do so. Once this new feature is ready we will contact you about it and explain how things work and what options you have.

When you have any questions already feel free to PM or email me!

Share this post


Link to post
Share on other sites

Depends on what you want to do. I have several reports saying that it is MP compatible, means several players can have conversations with one AI etc. For simple conversations just make sure to run the functions on every client and you should be good. There was one guy who adapted the system to meet his clan's requirements. Last he wrote me was that he conisdered publishing the adapted version because it could be useful to other clans, not sure if he actually did though. In short: Try it yourself!

Share this post


Link to post
Share on other sites
Depends on what you want to do. I have several reports saying that it is MP compatible, means several players can have conversations with one AI etc. For simple conversations just make sure to run the functions on every client and you should be good. There was one guy who adapted the system to meet his clan's requirements. Last he wrote me was that he conisdered publishing the adapted version because it could be useful to other clans, not sure if he actually did though. In short: Try it yourself!

Sure thing, ill let you know how well it works out.

Share this post


Link to post
Share on other sites

Trying to implement this into an MP scenario. Currently receiving this error on IP_fnc_addConversation:

Error loading control C:\Users\Lynn\Documents\Arma 3 - Other Profiles\Kinch\mpmissions\co08_tf_titan_x1.Altis\description.ext/RscTitles/IP_DLG_SIMPLESENTENCE/Controls/IP_BOX_MAIN/

and in-game I receive the "Conversation has no sentences!" hint error. Even though I'm pointing it to the default opener conversation.

Only changes I've made thus far is removing RscTitles from dialogs.hpp since I have RscTitles brackets already defined in description.ext and having MissionConversations.hpp inside the conv folder. Any idea what might be messing up?

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×