SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 14/04/2015, 04:54 PM   #1
Misiur
High-roller
 
Misiur's Avatar
 
Join Date: Jul 2009
Location: Poland
Posts: 2,540
Reputation: 552
Default y_dialog and y_inline

Introduction

This tutorial continues my series on the new features available in YSI 3.0. As I strive to get it stable and released, these tutorials should give people an idea of what's available and thus make it easier for people to test them and find bugs (please report any you find).

There are a number of dialog processing systems already, but they all have (IMHO) one fundamental flaw - they all still rely on dialog IDs. "y_dialog" does away with this requirement, instead maintaining a record of what IDs are in use internally and providing an API to get an available free one (if you even need to).

Example

Code:
new
    id = Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Title", "Message", "Button 1");
This is basically the same API as before (you can still use the old functions and the system will register those IDs as in use), but with no "dialog" parameter. In actual fact, it is still there, it's just at the end.

Reuse

The optional existence of the "dialog" parameter means you can ignore it entirely (the second button parameter can also be left out), or you can give an ID when it is appropriate.

Showing a dialog to some set of players:


Code:
new
    id = Dialog_ObtainID();
foreach (new i : Player)
{
    if (ShouldSeeDialog(i))
    {
        Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Title", "Message", "Button 1", .dialog = id);
    }
}

This way the same dialog seen by every player will always have the same ID (making processing easier). You could even register the ID in "OnGameModeInit" and always use that ID, ensuring that no two dialogs will ever conflict (and as with any YSI library, this works in all scripts at once):

Code:
#include <YSI\y_dialog>

new
    gID = -1;

public OnGameModeInit()
{
    gID = Dialog_ObtainID();
}

public OnPlayerConnect(playerid)
{
    Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Welcome", "Welcome to the server!", "OK", "Cancel", gID);
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if (dialogid == gID)
    {
        printf("player %d pressed %d", playerid, response);
    }
    return 1;
}

Or, if it is a dialog that will only be used once, you can tell the system to reclaim the ID after no-one can see it ("garbage" collection):

Code:
new
    id = Dialog_ObtainID();
foreach (new i : Player)
{
    if (ShouldSeeDialog(i))
    {
        Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Title", "Message", "Button 1", .dialog = id);
    }
}
Dialog_Garbage(id);

"Garbage" will be automatically set for any dialog which is only shown to one player and for which no explicit dialog ID was provided:

Code:
new
    id = -1;
foreach (new i : Player)
{
    if (ShouldSeeDialog(i))
    {
        id = Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Title", "Message", "Button 1", .dialog = id);
    }
}

In the code above "id" is initially set to "-1" (which means "assign an ID"), so the system assigns an ID for the first player, marks the ID as garbage (to be reclaimed when no-one can see the dialog any more) and returns this new ID. When the dialog is shown to the second player the existing ID is re-used but "garbage" status IS NOT cleared. This makes the code above DIFFERENT to the code in which "Dialog_ObtainID" is explicitly called first. Your choice of function call should reflect this difference.

Functions

There are a few other functions available for use:
  • Dialog_Get(playerid)

    Get the ID of the dialog this player can currently see. Note that if you call this function in "OnDialogResponse" it WILL NOT return the correct ID as the player can no longer see it (but you still have "dialogid" there anyway).

  • Dialog_Set(playerid, dialogid)

    It's doubtful that you will ever need this function, but this is the opposite of "Dialog_Get".

  • Dialog_Hide(playerid)

    Hide the dialog that the player is currently viewing.

  • ShowPlayerDialog(playerid, dialog, style, string:title[], string:caption[], string:button1[], string:button2[])

Hooked function to show a dialog with the given ID, and reserve that ID in the system.


Callbacks

There is one very important feature of y_dialogs that makes it (again, IMHO) vastly better than any other dialog processing system and that is it's ability to use "y_inline" for single dialog response processing instead of "OnDialogResponse":

Code:
public OnPlayerConnect(playerid)
{
    inline Response(pid, dialogid, response, listitem, string:inputtext[])
    {
        #pragma unused pid, dialogid, response, listitem, inputtext
        SendClientMessage(playerid, 0xFF0000AA, "You clicked a button!  Good for you!");
        // Inline function will end here.
    }
    Dialog_ShowCallback(playerid, using inline Response, DIALOG_STYLE_MSGBOX, "Title", "Message", "Button 1");
    // Main function will end here.
}

That is all there is to processing a dialog using this system. The dialog id does not appear anywhere in that code (there is the variable "dialogid" passed to the inline function, but you don't need it). "inline" functions are mostly like normal functions, except they can be embedded inside other functions (including inside other "inline" functions).

There are a few VERY important things to note here:
  • The callback "OnPlayerConnect" has a parameter called "playerid", the callback "OnDialogResponse" ALSO has a parameter called "playerid", and the "Response" inline function has the same parameters as "OnDialogResponse". However, you can't have two variables with the same name in one function so the second "playerid" has been renamed "pid".
  • Further to the point above, "SendClientMessage" uses "playerid" NOT "pid". "OnPlayerConnect" is called when the player connects, "Response" is called when the player clicks something on the dialog (which could be many hours later if they're AFK). Despite this fact, you can still use "playerid" (and any other variable from the enclosing function) inside "Response" thanks to a feature called "closures".
  • Strings do work, but strings passed to the enclosing function (there are none here) DO NOT work as they're a little different. Also, any string that is a parameter to an inline function (for example "inputtext") must be declared with the tag "string:", as above.
This style of coding keeps the reponse processing of a dialog with the place where it is shown, and removes the worry of dialog IDs entirely. You can also use public callbacks instead of inline functions with "using callback Whatever" instead of "using inline Whatever".

You can also combine processing and show a dialog with a callback to mulitple people (and mark it as garbage or not).
Misiur is offline   Reply With Quote
Old 02/05/2015, 11:37 PM   #2
RaeF
Huge Clucker
 
Join Date: Dec 2014
Location: Indonesia
Posts: 265
Reputation: 27
Default Re: y_dialog and y_inline

I got strange bug:

Code:
				
				inline Dialog_Register(pid, response, listitem, string:inputtext[])
				{
				    if(!response)
				    {
				        Kick(playerid);
				    }
				}
response doesn't work well, although i press button 1 or button 2, that just kick me ._.
RaeF is offline   Reply With Quote
Old 02/05/2015, 11:59 PM   #3
Crayder
High-roller
 
Crayder's Avatar
 
Join Date: Sep 2013
Location: Flames of Hell
Posts: 3,863
Reputation: 588
Default Re: y_dialog and y_inline

Quote:
Originally Posted by RaeF View Post
I got strange bug:

Code:
				
				inline Dialog_Register(pid, response, listitem, string:inputtext[])
				{
				    if(!response)
				    {
				        Kick(playerid);
				    }
				}
response doesn't work well, although i press button 1 or button 2, that just kick me ._.
One button return a canceled response, the other sends a true response. Btw, why would you use kick as a test method? XD

Why not just do this?
Code:
				
				inline Dialog_Register(pid, response, listitem, string:inputtext[])
				{
				    switch(response)
				    {
				        case 0: SendClientMessage(playerid, -1, "Negative");
				        default: SendClientMessage(playerid, -1, "Positive");
				    }
				}
__________________
Those who deserve reputation, do not need to beg for it.
Also, don't expect the help you need when offering reputation, you'll just be attracting Rep Hunters.
Join SA-MP Discord!
Crayder is offline   Reply With Quote
Old 03/05/2015, 12:33 AM   #4
RaeF
Huge Clucker
 
Join Date: Dec 2014
Location: Indonesia
Posts: 265
Reputation: 27
Default Re: y_dialog and y_inline

DELETED, already solved

im missing dialogid param lol
RaeF is offline   Reply With Quote
Old 21/05/2015, 11:37 PM   #5
RaeF
Huge Clucker
 
Join Date: Dec 2014
Location: Indonesia
Posts: 265
Reputation: 27
Default Re: y_dialog and y_inline

Need help, inline not getting called
It just print

Debug: Called 3
Debug: Called 1
Debug: Called
and Lel doens't getting called.
But the Dialog show up.
Code:
public OnPlayerClickPlayerTextDraw(playerid, PlayerText:playertextid)
{
	print("Debug: CAlled 3");
	if(playertextid == textdraw_panel_player[playerid][5])
	{
		print("Debug: CAlled 1");
		inline Response(pid, dialogid, response, listitem, string:inputtext[])
		{
			#pragma unused pid, dialogid, response, listitem, inputtext
			print("Lel");
		}
		print("Debug: CAlled");
		Dialog_ShowCallback(playerid, using inline Response, DIALOG_STYLE_INPUT, "Masukan password baru", "Masukan password baru akun anda dibawah ini:", "Ok", "Batal");
	}
	return 1;
}
But when use standar ( Not using inline ), it's called.
__________________
Release:

- Nothing - I dont have idea to release something.
RaeF is offline   Reply With Quote
Old 28/12/2015, 10:24 PM   #6
andyandyy8
Big Clucker
 
Join Date: Apr 2013
Posts: 54
Reputation: 3
Default Re: y_dialog and y_inline

Hello! I have found a bug. Dialogs(ShowPlayerDialog or Dialog_Show(playerid, ....., .dialog = 8 are not working when this library is included. Do you have any tip?
It is from:
hook OnDialogResponse, i tried to change the timer with the content of the function but a bug appeared:
Simple dialogs are working( Dialog_Show(..... ,.dialog = value) ) but the complex one aren't working. (Dialog_ShowCallback).
Thank you!
andyandyy8 is offline   Reply With Quote
Old 05/05/2018, 01:19 PM   #7
DBZdabIt3Bro7
Little Clucker
 
Join Date: Sep 2017
Location: Lovely name, right?
Posts: 41
Reputation: 8
Default Re: y_dialog and y_inline

Quote:
Originally Posted by Crayder View Post
One button return a canceled response, the other sends a true response. Btw, why would you use kick as a test method? XD

Why not just do this?
Code:
				
				inline Dialog_Register(pid, response, listitem, string:inputtext[])
				{
				    switch(response)
				    {
				        case 0: SendClientMessage(playerid, -1, "Negative");
				        default: SendClientMessage(playerid, -1, "Positive");
				    }
				}
Can you clarify?

BUTTON1 text = left button? (response = 0)
BUTTON2 text = right button? (response = 1)


(I'm aware I bumped a topic from 2015, and I meant to do it.)
DBZdabIt3Bro7 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Server crash when using y_dialog - y_inline Ahmad45123 Scripting Help 1 01/01/2015 11:31 AM
A y_inline and y_dialog issue yxliang Scripting Help 9 08/07/2013 09:59 AM


All times are GMT. The time now is 04:27 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.