Jump to content
IndeedPete

Spin-Off Release: Simple Conversation System

Recommended Posts

Hi Pete, sorry if i'm a bit late.

I'm doing my first mission and I'm trying to introduce your mod.
But the point is that i want to interact with the NPC's and display an icon using the "addaction" function into ini field before it opens the dialog window.
So,  how can do to insert the script for it works?!

That's the ini field of the NPC:

this addAction ["<img size='6' shadow='0.8' image='Img\icons\player\icon_talk.paa'/></t>" , [dude_01, opener"] call IP_fnc_addConversation , [], 1, true, true, "", "", 2, false];


So when i use it, the talk icon doesn't appear when you're near the NPC, you have to use the scroll menu and it shows the icon and the "opener" conversation function.
 

Share this post


Link to post
Share on other sites

You probably mean this hold action they introduced in Apex. You could adapt this: https://forums.bohemia.net/forums/topic/192346-woah-woah-woah-bi-trying-to-sneak-one-in/#entry3058266

Share this post


Link to post
Share on other sites

Hello there! This may be a shot in the dark but I'm hoping you can help as this is by far one of the best Conversation scripts I've come across, So I am using ALiVE to spawn Eastern Civillians in a Afghan Style Sim, I'm brand new to this coding aspect and don't understand how to make the talk action available with them

Share this post


Link to post
Share on other sites

Not sure. Does AliVE provide you with a way to access the spawned units and/or their init lines at start up? If not, you'd be stuck with constant or periodic looping over allUnits.

Share this post


Link to post
Share on other sites

I believe so, it talks about Script Snippets and using

 

Extended_Init_EventHandlers { class Man { init = "_this call (compile preprocessFileLineNumbers 'my_script.sqf')"; }; };

 

to call my script to usage, but I'm not sure how it'll work as I said I'm fairly new

 

Share this post


Link to post
Share on other sites

For reference: http://alivemod.com/wiki/index.php/Script_Snippets#Adding_Custom_Inits_to_Spawned_Units

 

In that case it should be relatively simple. Untested code that would go into your description.ext:

class Extended_Init_EventHandlers {
	class Man {
		init = "if !(isPlayer _this) then {_this call BIS_fnc_objectVar; [_this, """MyTopic"""] call IP_fnc_addConversation;}";
	};
};

 

Share this post


Link to post
Share on other sites

Hey IndeedPete,

 

im using your conversation script, but i get an error. The opener works fine, but if I click on one of the sentences i get this error:

https://imgur.com/a/7ig0icf

 

my init.sqf:

Spoiler

player setVariable ["IP_LiveFeed", true];

IP_Goatguy setVariable ["IP_LiveFeed", true];
IP_Goatguy setVariable ["IP_Avatar", "conv\img\capek.jpg"];
IP_Goatguy setVariable ["IP_ConvSpecial", "Ziegenhüter"];
[IP_Goatguy, "capek_opener"] call IP_fnc_addConversation;

[] spawn {
    waitUntil {player distance IP_Goatguy < 30};
    
    [IP_Goatguy, "Hallo, ihr guten Menschen! Fremde sind hier nicht gerne gesehen... Bitte, kommt zu mir!", "SIDE"] call IP_fnc_simpleSentence;
}; 

 

my description.ext:

Spoiler

#include "conv\cfg\defines.hpp"
#include "conv\cfg\dialogs.hpp"
#include "missionConversations.hpp"


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

 

 

my missionConversation.hpp:

Spoiler

class Conversations
{
	class capek_exit
	{
		exit = 1;
		expression = "nul = [IP_Goatguy, 'Lebt wohl!', 'DIRECT', 3] spawn IP_fnc_simpleSentence;";
		sentences[] = {"Auf Wiedersehen!"};
	};
	class capek_opener
	{
		arguments[] = {"(name player)"};
		responses[] = {"capek_gods", "capek_back","capek_exit"};
		sentences[] = {
			"Hallo mein Name ist Colonel O'Connor und das ist Major Walker. Wer bist du?",
			"Willkommen auf Sadrade, %1. Ich bin Capek. Fremde sind hier nicht gerne gesehen. Sobald euch die Schlangen-Wachen entdecken, werden die Götter euch töten. Ihr solltet am Besten ungesehen bleiben und euch nicht in die Nähe des oberen Viertels wagen. Ihr könnt aber ungestört in die untere Stadt, wenn ihr euch nicht zu auffällig benehmt."
		};
	};
	class capek_back
	{
		responses[] = {"capek_gods", "capek_location", "capek_abouthim","capek_exit"};
		sentences[] = {
			"Ich würde gerne über was anderes reden.",
			"Ja?"
		};
	};
	class capek_location
	{
		responses[] = {"capek_back", "capek_exit"};
		sentences[] = {
			"Was ist das hier für ein Ort?",
			"Das ist Sadrade. Die Götter haben diesen Ort erschaffen. Wir leben hier um ihnen zu dienen."
		};
	};	
	class capek_abouthim
	{
		responses[] = {"capek_back", "capek_exit"};
		sentences[] = {
			"Erzähle mir was über dich.",
			"Die, die mich kennen, nennen mich Capek. Ich bin nur ein einfacher Ziegenhüter. Mein ganzes Leben lang habe ich nichts anderes getan."
		};
	};	
	class capek_gods
	{
		responses[] = {"capek_killgods", "capek_back", "capek_exit"};
		sentences[] = {
			"Schlangen-Wachen, Götter?",
			"Die Götter leben oben in der Haupt-Pyramide und wollen nicht gestört werden. Die Schlangen-Wachen sind ihre Diener und töten jeden, der nicht an sie glaubt."
		};
	};
	class capek_killgods
	{
		responses[] = {"capek_offerhelp", "capek_back", "capek_exit"};
		sentences[] = {
			"Das klingt so als währt ihr nicht zufrieden...",
			"Ja, sie haben uns Frauen und Kinder genommen. Die Männer haben sie in die Minen gebracht. Mich und ein paar andere zwingen Sie dazu ihre Nahrung zu produzieren.",
			"Hör zu, wir sind durch das runde Tor im Canyon gekommen, du kennst es wahrscheinlich als Chaapa'ai. Meine Freunde und ich sind entsprechend ausgebildet und ausgerüstet um die Götter zu töten. Wenn du es uns erlaubst, helfen wir dir.",
			"Die Götter töten? Das ist doch unmöglich! Wenn ihr stimmt, was das sagt, dann... nein, es ist nicht möglich! Bringt einen Beweis!"
			};
		};	
	class capek_offerhelp
	{
		responses[] = {"capek_brother", "capek_back", "capek_exit"};
		sentences[] = {
			"Hör zu, wir sind durch das runde Tor im Canyon gekommen, du kennst es wahrscheinlich als Chaapa'ai. Meine Freunde und ich sind entsprechend ausgebildet und ausgerüstet um die Götter zu töten. Wenn du es uns erlaubst, helfen wir dir.",
			"Die Götter töten? Das ist doch unmöglich! Wenn ihr stimmt, was das sagt, dann... nein, es ist nicht möglich! Am Besten sprecht ihr mit meinem Bruder..."
		};		
	};
	class capek_brother
	{
		responses[] = {"capek_back", "capek_exit"};
		sentences[] = {	
			"Dein Bruder?",
			"Ja, er ist... nun, er wird es euch selbst erklären. Er hält sich meistens am Markt auf. Sein Name ist Faadi.",
			"Okay, wir reden mit deinem Bruder."
		};
	};	
//Seargeant	
	class sgt_exit
	{
		exit = 1;
		expression = "nul = [IP_Sgt, 'Bis Später, Sir.', 'DIRECT', 3] spawn IP_fnc_simpleSentence;";
		sentences[] = {"'Weggehen'"};
	};
	class sgt_opener
	{
		responses[] = {"sgt_how", "sgt_back", "sgt_exit"};
		sentences[] = {
			"Seargeant James?",
			"Sir, der Kontroll Kristall vom DHD wurde entfernt! Wir können die Erde nicht mehr anwählen!"
		};
	};
	class sgt_back
	{
		responses[] = {"sgt_how", "sgt_location", "sgt_abouthim", "sgt_exit"};
		sentences[] = {
			"Ich würde gerne über was anderes reden.",
			"Sir?"
		};
	};	
	class sgt_how
	{
		responses[] = {"sgt_crystal", "sgt_back", "sgt_exit"};
		sentences[] = {
			"Wie konnte das passieren? Wieso ist das nicht früher aufgefallen?",
			"Das Stargate Center hat wohl nur die visuelle Bestätigung für das DHD durch das MALP gehabt. Die Abdeckung war geschlossen, wir konnten nicht sehen, ob der Kontroll Kristall gefehlt. Es ist mir gerade erst aufgefallen."
		};
	};
	class sgt_crystal
	{
		responses[] = {"sgt_back", "sgt_exit"};
		sentences[] = {
			"Woher bekommen wir nun einen neuen Kristall?",
			"Ich weiß es nicht, Sir. Es sieht so aus, als wäre er mit Absicht entfernt worden. Irgendwo hier in der Gegend muss sich einer befinden.",
			"Okay, Seargeant, Sie bleiben mit dem Corporal hier und bewachen das Tor. Major Walker und ich werden dem Pfad folgen und sehen, was wir finden. Sie melden sich zur jeden vollen Stunde.",
			"Verstanden, Sir!"
		};
	};
	class sgt_location
	{
		responses[] = {"sgt_back", "sgt_exit"};
		sentences[] = {
			"Was ist das hier für ein Ort?",
			"Sir, das ist P42-977. Ein Wüstenplanet, dessen Fauna fast identisch zu unserer Erde ist. Es ist zwar extrem heiß, aber die Luft lässt sich atmen. Mehr wissen wir auch nicht, Sir. Der General hat uns angewiesen mehr herauszufinden."
		};
	};	
	class sgt_abouthim
	{
		responses[] = {"sgt_back", "sgt_exit"};
		sentences[] = {
			"Erzähle mir was über dich.",
			"Sir, mit allem gebührendem Respekt, aber es ist keine Zeit für eine Märchenstunde."
		};
	};
};	

 

I can't figure out what i've done wrong. I doublechecked the missionConversations.hpp for errors, but can't find any.

Does anyone have any idea what I am doing wrong?

 

Share this post


Link to post
Share on other sites

Try to provide your player with a variable name in the editor.

Share this post


Link to post
Share on other sites

It is possible to work with stringtables?

 

I tried it like this:

	class sgt_what
	{
		responses[] = {"sgt_how", "sgt_back", "sgt_exit"};
		sentences[] = {
			STR_OConnor_Chapter01_Scene01_Dialog02,
			STR_James_Chapter01_Scene01_Dialog02
		};
	};

But ingame the STR_ .. stuff is shown instead of the dialog.

 

Any idea how i can use stringtables?

 

 

Share this post


Link to post
Share on other sites

Sure, same as in any other config type file:

 

class startOpen: radioOpen
{
  responses[] = {"startQuestion", "startConfirm"};
  sentences[] = {$STR_IP_KSK_MEW_CONV_GENERAL_RADIO_OPEN, $STR_IP_KSK_MEW_CONV_START_OPEN_1, $STR_IP_KSK_MEW_CONV_START_OPEN_2, $STR_IP_KSK_MEW_CONV_START_OPEN_3};
};

The Dollar symbol $ does the trick.

  • Like 2

Share this post


Link to post
Share on other sites

Hey Pete, not sure if you have the time to respond to this, but I was wondering if there was a way to make responses conditional.
For clarification, at the moment you put multiple response options in each class. Is there a way to have an option unavailable, such as if x is true, then y is available as a response, but if x is not true, then y is not available?
I know that theoretically one could make another class that just doesn't have that response, but I imagine that could get very time consuming even for just a single conversation.

If you don't know of a way to do that, do you know of where one might want to start with rewriting portions to be able to do that?

 

Thanks in advance

Share this post


Link to post
Share on other sites

I believe that does work already, albeit different than you think. Check this part from the original post:

class MyFirstConversation // Name of the conversation.
{
    ...           
	condition = ""; // Condition (Boolean) which causes the conversation to show up as action or response in MC. Empty string means conversation will always show up.
	...
};

Meaning you put your condition in the response's class and it will be evaluated for every class that has it set as response. That said, I haven't tested it in quite some time.

Share this post


Link to post
Share on other sites

Ah, I think I see. So, as an example, doing an example like below, if intel = false, then when someone is conversing with the AI, there is no option to select the "details" related response. Do I have that correct?
 

class opener
{
	responses[] = {"information", "details", "exit"};
	sentences[] = {
		"...",
		"..."
	};
};
class information
{
	responses[] = {"details", "exit"};
	sentences[] = {
		"...",
		"..."
	};
};
class details
{
	condition = "intel = true";
	responses = {"exit"};
	sentences[] = {"..."};
};

A separate question. I know that one can do arguments for these classes in order to do something like (name player) included in sentences. Is there a way to do that for the simpleconversation function as well?

Share this post


Link to post
Share on other sites

Ah, almost. 😄 When checking boolean variables, the correct syntax is just the variable:

class details
{
	condition = "intel";
	responses = {"exit"};
	sentences[] = {"..."};
};

Although, with global variables, I'd advise null-checks to prevent script errors when the value hasn't been set yet:

class details
{
	condition = "!(isNil 'intel') && {intel}";
	responses = {"exit"};
	sentences[] = {"..."};
};

As for arguments, check the original post again:

class MyFirstConversation // Name of the conversation.
{
    	arguments[] = {"(name player)"}; // Arguments passed to each sentence. Can be used via %1, %2, etc.
	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.
};

 

Share this post


Link to post
Share on other sites

Thanks, I think I understand the condition part of those classes a bit more!
As for arguments, I'm not sure if I'm not understanding something or messed it up, but I did realize there's been a miscommunication that's my fault. 😅 I meant simpleSentence, not simpleConversation.
I was curious how it would work for the simpleSentence function, which I think is the one that pops up on the bottom of the screen with liveFeed if its on. I tried making a unit say something along the lines of "Good bye, %1" with %1 being (name player), but it didn't work for simpleSentence and I'm not sure if that's because there's no functionality for that, or if I should've done things different.
As annoying as I know it is, I don't actually have that code that didn't work, since I ended up deleting it and not trying that when it didn't work after a few tries, then making the mission. However, I'll try to recreate it, just mind any weird errors.

	class exit
	{
		exit = 1;
		arguments[] = {"(name player)"};
		expression = "nul = [civ_1, 'Good bye, %1!', 'DIRECT', 3] spawn IP_fnc_simpleSentence;";
		sentences[] = {"Good bye!"};
	};

After rewriting that, I would imagine if I wanted to put an argument in a simpleSentence, it'd have to be a part of the line where it spawns the simpleSentence, right? If it does, I have close to zero clue on what to actually do to make that work.

Share this post


Link to post
Share on other sites

Ah, okay. That's a different thing if you run it in the expression. That way, you need to format the text yourself: https://community.bistudio.com/wiki/format

class exit
{
  exit = 1;
  expression = "nul = [civ_1, (format ['Good bye, %1!', (name player)]), 'DIRECT', 3] spawn IP_fnc_simpleSentence;";
  sentences[] = {"Good bye!"};
};

 

Share this post


Link to post
Share on other sites

Oh, I see. That makes sense. Thanks for the help Pete. Hoping I can use this script to add some extra options for players in ops. Seems to work well so far with dedicated.

Share this post


Link to post
Share on other sites

Having a line 3 error in my init.sqf so here it is.

Spoiler

player setVariable ["IP_LiveFeed", true];

 

hostage setVariable ["IP_LiveFeed", true];
hostage setVariable ["IP_Avatar", "conv\img\vp.jpg"];
hostage setVariable ["IP_ConvSpecial", "Vice President Of The United States"];
[hostage, "opener"] call IP_fnc_addConversation;

 

hostager setVariable ["IP_ConvSpecial", "Senator Of Oklahoma"];
[hostager, "senatoropener"] call IP_fnc_addConversation;

Ive replaced every unit name 1000x and cant figure it out. Just for the hell of it ill add my missionConversations.hpp

Spoiler

class Conversations
{
    class exit
    {
        exit = 1;
        sentences[] = {"[End Conversation]"};
    };
    class opener
    {
        responses[] = {"start"};
        sentences[] = {
            "Start Verification",
            "Okay, ask away."
        };
    };
    class start
    {
        responses[] = {"vicepresident"};
        sentences[] = {
            "Mr. Vice President, we're with Task Force 118, we need to ask you a few questions before we can get you out of here.",
            "Okay, ask away."
        };
    };
    class vicepresident
    {
        responses[] = {"fullname"};
        sentences[] = {
            "Mr. Vice President, We're verifying that you are who you say you are. Before I ask i need to know if you've had any sort of trauma that may lead to you answering incorrectly?",
            "Well I hit my head pretty hard when I was being pulled out of my car but, i believe I am okay."
        };
    };
    class fullname
    {
        responses[] = {"dob"};
        sentences[] = {
            "What is your full name given at birth?",
            "Kahle Robert Russ."
        };
    };
    class dob
    {
        responses[] = {"ssn"};
        sentences[] = {
            "What is the date of your birth?",
            "05/14/1992."
        };
    };
    class ssn
    {
        responses[] = {"maidenname"};
        sentences[] = {
            "What is your government issued Social Security Number?",
            "34-8-125."
        };
    };
    class maidenname
    {
        responses[] = {"finish"};
        sentences[] = {
            "What is your mother's maiden name?",
            "Jones."
        };
    };
    class finish
    {
        responses[] = {"exit"};
        sentences[] = {"Templar Main, This is Templar Actual. Package is safe and secure. Identity has been verified. We are homebound in 5 mikes."};
        };
    };
    class senatoropener
    {
        responses[] = {"starter"};
        sentences[] = {
            "Start Verification",
            "Are you serious? After what we've been through you have ask questions? I uhh guess but be quick."
        };
    };
    class starter
    {
        responses[] = {"senator"};
        sentences[] = {
            "Senator, we're with Task Force 118, we need to ask you a few questions before we can get you out of here.",
            "Are you serious? After what we've been through you have ask questions? I uhh guess but be quick."
        };
    };
    class senator
    {
        responses[] = {"fullnamer"};
        sentences[] = {
            "Senator Avery, we're verifying that you are who you say you are. Before I ask i need to know if you've had any sort of trauma that may lead to you answering incorrectly?",
            "NO! None at all, be quick asshole!"
        };
    };
    class fullnamer
    {
        responses[] = {"bod"};
        sentences[] = {
            "What is your full name given at birth?",
            "My name is uhh... Avery Harry Yang."
        };
    };
    class bod
    {
        responses[] = {"ssner"};
        sentences[] = {
            "What is the date of your birth?",
            "It's 10/02/1998."
        };
    };
    class ssner
    {
        responses[] = {"maidennamer"};
        sentences[] = {
            "What is your government issued Social Security Number?",
            "71-9-452."
        };
    };
    class maidennamer
    {
        responses[] = {"finisher"};
        sentences[] = {
            "What is your mother's maiden name?",
            "Umm, Smith."
        };
    };
    class finisher
    {
        responses[] = {"senatorexit"};
        sentences[] = {
            "Templar Main, This is Templar Actual. Secondary Package's Identity cannot be verified. Be advised that Verification questions were answered almost all incorrectly. We are homebound with scarecrow, time now.",
            "This is outrageous! You american dogs will die! **Takes thumb off remote detonator** WHY ISNT IT WORKING!"
        };
    };
    class senatorexit
    {
        exit = 1;
        sentences[] = {
        "[End Conversation]",
        };
    };
};

and finally ill add my description.ext

Spoiler

#include "conv\cfg\defines.hpp"
#include "conv\cfg\dialogs.hpp"
#include "missionConversations.hpp"

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

author = "Oz";
OnLoadName = "Operation:Gauntlet";

I got it to work one time and now I have no idea why it isnt working. All my conv files are inside so i am truly clueless...

Share this post


Link to post
Share on other sites

In the last line of your script, you refer to a hostager while you probably meant to write hostage.

Share this post


Link to post
Share on other sites

Okay, what does the error message say?

Share this post


Link to post
Share on other sites

Great script @IndeedPete ! It offers lots of opportunities for mission making.

I did some quick testing as I plan on using it in a mission. Everything is working fine for me, except for the LiveCam which I cannot get to work. The dialogues/sentences functions work perfectly, but I get no LiveCam though. I did test the demo mission without any mods to see if one mod could mess with the cam script but even in vanilla arma in the demo mission, I don't get any LiveCam. I checked the RPT too to see if there was any error but couldn't find anything. I didn't see anyone mentioning this issue in the thread so maybe it's on my end. Not sure if you still plan to patch/update the script, and if not, it's okay. It's not to big of a problem not having the liveCam as the rest of the script works still 😉

Anyway, thanks a lot for putting this script together and sharing it!

 

Share this post


Link to post
Share on other sites

It might be BI changed something and now it doesn't work anymore. I'm personally only using the multiple choice dialog version these days.

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

×