Tutorial -> How to make a dialog
#1

Dialogs, a wonderful new feature in 0.3.
This tutorial is created to help you understand and implement them.
First, you must understand the difference between a guide and a tutorial, a guide shows you exactly what to do, and usually gives you the code; a tutorial shows you how to do it, and may give some examples. I am going against my better judgement and implementing some guide parts, just to not be annoyed by the people that don't know how to write their own code.

Note: Putting a dialog in OnPlayerConnect will make the spawn gui not visible.

Understand
Dialogs are not things that are created, they are shown, or they are not.
It is possible to make them creatable, but is quite un-efficient, I will show you some possibilities later in the tutorial.
First, the function:
pawn Код:
ShowPlayerDialog(playerid, dialogid, style, caption[], info[], button1[], button2[])
Second, the definition:
  • playerid: the user to which you want the dialog to be shown to
  • dialogid: the id of the dialog, used for OnDialogResponse
  • style: specifies what kind of dialog is wanted, an input box(allows user input), a msgbox(shows text to the user), or a listbox(allows user to choose from a list of items)
  • caption: a title for the box, should be brief, and to the point(use "Login" not "insert password to login")
  • info: the main text of the box, used to describe what the box is about, listitems are placed in here (seperated by new lines (\n)) and tabs can be placed by using \t
  • button1: the text of button1 (on the left) usually "yes" or "accept" or "done"
  • button2: the text of button2 (on the right) usually "no" or "cancel"

Now, how to use these parameters correctly
pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE, DIALOG_STYLE_MSGBOX, "WARNING", "Warning, your money has dropped below 100\nwould you like to take out a loan?", "yes", "no");
This would make a dialog appear to playerid, as a msgbox, a title of WARNING, and it saying Warning, your money has dropped below 100<linebreak>would you like to take out a loan? and yes or no buttons.
simple.
pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE + 1, DIALOG_STYLE_INPUT, "Login", "Welcome back\nInsert password to login", "login", "cancel");
This would make a dialog appear to playerid, with the style of input, a title of login, and it saying "Welcome back<linebreak>Insert password to login." With "login" and "cancel" buttons.
Not quite as simple, yet still easy.
pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE + 2, DIALOG_STYLE_LIST, "Destination", "LSPD\nLVPD\nSFPD\nLS Bank\nLS Airport", "warp", "cancel");
You should be able to figure out most of it, but now it is a list, with the items of
  • LSPD
  • LVPD
  • SFPD
  • LS Bank
  • LS Airport
Simple? I hope so.

Implement
NOTE: I HAVE NOT TESTED ANY OF THESE METHODS, THEY SHOULD WORK.
As I was saying before there can be a semi-dynamic way. Here it is:
pawn Код:
#define MAX_DIALOGS (15)
#define DIALOG_BASE (324)
enum DialogInfo
{
  DTaken,
  DStyle,
  DCap[64], //I have never used an array(string) in an enum like this before, untested
  DInfo[512], //if you don't need it this big make it smaller.
  DBut1[24],
  DBut2[24]
}
new Dialogs[MAX_DIALOGS][DialogInfo];
//handleid is NOT dialog id, multiple dialogs with the same text can be shown with different id's
CreateDialog(style, caption[], info[], button1[], button2[]) //returns handleid
{
  new handleid = 0;
//Tempted to use foreach here, not going to, for portability.
  for ( ; handleid < MAX_DIALOGS; handleid++)
  {
    if (Dialogs[handleid][DTaken] == 0) break;
  }
  Dialogs[handleid][DTaken] = 1;
  Dialogs[handleid][DStyle] = style;
  format(Dialogs[handleid][DCap], sizeof(Dialogs[handleid][DCap]), caption);
  format(Dialogs[handleid][DInfo], sizeof(Dialogs[handleid][DInfo]), info);
  format(Dialogs[handleid][DBut1], sizeof(Dialogs[handleid][DBut1]), button1);
  format(Dialogs[handleid][DBut2], sizeof(Dialogs[handleid][DBut2]), button2);
  return handleid;
}

ShowDialog(playerid, dialogid, handleid)
{
  if (Dialogs[handleid][PTaken] == 0) return 0;
  return ShowPlayerDialog(playerid, dialogid, Dialogs[handleid][PStyle], Dialogs[handleid][PCap], Dialogs[handleid][PInfo], Dialogs[handleid][PBut1], Dialogs[handleid][PBut2]);
}
I say semi-dynamic because there is an unknown limit of how many dialogs can be used, hence the variable will have to be changed per script.


now a non-dynamic, easily changeable, way:
pawn Код:
#define LOGINDIALOGPARAMS(%1,%2) %1, %2, DIALOG_STYLE_INPUT, "Login", "Welcome back!\nInsert password to login", "login", "cancel"
can be used by
pawn Код:
ShowPlayerDialog(LOGINDIALOGPARAMS(playerid, dialogid));
and 2 different ways of doing that are
pawn Код:
#define LOGINDIALOG(%1,%2) ShowPlayerDialog(%1, %2, DIALOG_STYLE_INPUT, "Login", "Welcome back!\nInsert password to login", "login", "cancel")

//used like this

LOGINDIALOG(playerid, dialogid);

//or

#define LOGINDIALOGPARAMS DIALOG_STYLE_INPUT, "Login", "Welcome back!\nInsert password to login", "login", "cancel"

//used like this

ShowPlayerDialog(playerid, dialogid, LOGINDIALOGPARAMS);
then if you show that dialog in multiple spots, it is easier to change it by changing the define.

also a useful define to make it so no dialog is shown (if there is one up it goes away.) %1 is playerid.
pawn Код:
#define HidePlayerDialog(%1) ShowPlayerDialog(%1,-1,0,"","","","")
Continued on to next post.
Reply
#2

Respond
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
parameters broken down:
  • playerid: the player who responded to the dialog.123
  • dialogid: the id of the dialog responded to.123
  • response: if button1 was clicked or not.123
  • listitem: which item was selected if it was a listbox.3
  • inputtext: the string which was entered on an inputbox, or text of listitem selected.23
1 used in msgbox.
2 used in inputbox.
3 used in listbox.

We can see from this that msgbox is not that complicated.
Since listbox is the most complicated i will do that last.

pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE, DIALOG_STYLE_MSGBOX, "WARNING", "Warning, your money has dropped below 100\nwould you like to take out a loan?", "yes", "no");
from the above post, now the response would be.
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
  if (dialogid == DIALOG_BASE)
  {
    if (response == 1)
    {
      PlayerLoan[playerid] += 500;
      GivePlayerMoney(playerid, 500);
      SendClientMessage(playerid, 0xFFFFFFFF, "You have taken a loan from the bank for $500");
    }
    else
    {
      SendClientMessage(playerid, 0xFFFFFFFF, "No loan has been taken.");
    }
    return 1;
  }
  return 0;
}
Dandy bit of code, but ... what happened?
Well, that's what comments are for.


pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) //the callback
if (dialogid == DIALOG_BASE) //checks if the dialogid is the one we want (DIALOG_BASE, which is the msgbox)
if (response == 1) //checks if the "Yes" button was pushed
PlayerLoan[playerid] += 500; //sets a variable to show that the player has taken a loan
GivePlayerMoney(playerid, 500); //gives the player the money
SendClientMessage(playerid, 0xFFFFFFFF, "You have taken a loan from the bank for $500"); //shows a message to the player
else // "No" button has been pushed
SendClientMessage(playerid, 0xFFFFFFFF, "No loan has been taken."); //tells the player that he chose to not take a loan
return 1; //returns 1 because we successfully handled it.
return 0; //returns 0 pass it on to other scripts to see if they know what this dialog is.
And we move on.


Inputbox:
pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE + 1, DIALOG_STYLE_INPUT, "Login", "Welcome back\nInsert password to login", "Login", "Cancel");
You know the drill, commented.
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) //the callback
{
  if (dialogid == DIALOG_BASE + 1) //checking dialogid
  {
    if (response == 1) //making sure "Login" was pressed
    {
      if (!strcmp(inputtext, pPass[playerid])) //checking if it is the players password
      {
        LoginPlayer(playerid); //calling a function to log him in
      }
      else //incorrect password
      {
        ShowPlayerDialog(playerid, dialogid, DIALOG_STYLE_INPUT, "Invalid Password", "Invalid Password, try again", "Login", "Cancel"); //shows another dialog, with the same dialogid.
        LogAttempts[playerid]++; //increments a variable to know how many time he has tried to login
        if (LogAttempts[playerid] >=2) //is it greater then or equal to 2?
        {
          SendClientMessage(playerid, 0xFFFFFFFF, "Too many attempts, bye!"); //tells him what is about to happen
          SetTimerEx("kicker", 200, 0, "i", playerid); //if you can't figure out what this is, see below
        }
      }
    }
    else //pressed "Cancel"
    {
      SendClientMessage(playerid, 0xFFFFFFFF, "well if you aren't going to login, LEAVE"); //some message
      SendClientMessage(playerid, 0xFFFFFFFF, "okay, i will do it for you."); //another
      SetTimerEx("kicker", 200, 0, "i", playerid); //a timer that allows the player to see the messages before he is kicked.
    }
    return 1; //returns 1, it has been handled
  }
  return 0;
}
I sure hope you are understanding this, if you are not re-read until you do.

Listbox:
pawn Код:
ShowPlayerDialog(playerid, DIALOG_BASE + 2, DIALOG_STYLE_LIST, "Destination", "LSPD\nLVPD\nSFPD\nLS Bank\nLS Airport", "warp", "cancel");
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) //the callback
{
  if (dialogid == DIALOG_BASE + 2) //checking dialogid
  {
    if (response == 1) //warp has been pressed
    {
      switch (listitem) //a switch, not going to explain it here
      {
        case 0:SetPlayerPos(playerid, ...); //if (listitem == 0) Set... hey look, I just explained it.
        case 1:SetPlayerPos(playerid, ...); //if (listitem == 1) Set...
        case 2:SetPlayerPos(playerid, ...);
        case 3:SetPlayerPos(playerid, ...);
        case 4:SetPlayerPos(playerid, ...);
      }
      SendClientMessage(playerid, 0xFFFFFFFF, "warped to destination"); //a message to confirm the warp
    }
    else //pressed cancel
    {
      SendClientMessage(playerid, 0xFFFFFFFF, "warping canceled"); //confirmation of declination
    }
    return 1; //returns 1, it has been handled
  }
  return 0;
}

Bugs

There are some known bugs with dialogs (or manipulating any return values), one is if you try to format the string inputtext and the player entered a % (percentage sign) it will restart your server (confirmation needed)

Seif_ has made this fix:
pawn Код:
for(new s; s < strlen(inputtext); s++)
{
    if (inputtext == '%')
    {
        inputtext = ' ';
    }
}
Contributors
Seif_
****** (for immensely helping me understand PAWN)
Joe Staff
$ЂЯĢ


I hope you get it, any questions can be asked in this thread.
Reply
#3

when i do the non dynamic way, i get these errors:

Код:
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : warning 236: unknown parameter in substitution (incorrect #define pattern)
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : warning 236: unknown parameter in substitution (incorrect #define pattern)
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : error 029: invalid expression, assumed zero
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : warning 215: expression has no effect
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : error 001: expected token: ";", but found ")"
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : error 029: invalid expression, assumed zero
C:\Users\Thuron\Desktop\SAMP0.3\gamemodes\SIRRP.pwn(1161) : fatal error 107: too many error messages on one line
got it exactly like you have.
Reply
#4

bump
Reply
#5

I have same problem as turon
Reply
#6

thuron send the line where the error is

EDIT: Daren_Jacobson you forgot a ';' in the first pawn code
Reply
#7

on the line where i do this: ShowPlayerDialog(LOGINDIALOGPARAMS(playerid, dialogid));
Reply
#8

Quote:
Originally Posted by ArcticFox
thuron send the line where the error is

EDIT: Daren_Jacobson you forgot a ';' in the first pawn code
cause it isn't supposed to be there

i had a space in the params of the define, took them out, try it now.
Reply
#9

im gonna try to let it work as soon as i am home.
Reply
#10

i dont know whаt ur doing, but it just fucking does not work for me. here is all i got:

Код:
#define MainMenu(%1,%2) %1, %2, DIALOG_STYLE_LIST, "Master", "Enter\nBuy Points\nInformation", "Select", "Exit"
Код:
	if(!strcmp("/wmenu", cmdtext, true, 6))
	{
 	ShowPlayerDialog(MainMenu(playerid, dialogid));
		return 1;
	}
Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
	new PointsQuantity = strval(inputtext);
	new CurrMoney = GetPlayerMoney(playerid);
	gCheckout[playerid]= PointsQuantity*PointsCost;

	if(dialogid == DIALOGID)
	{
		if(response == 1)
		{
			if(listitem == 0) // DeathMatch Arena
					{
					if (2count >= 1count)
					{
					SetPlayerTeam(playerid,TEAM_1);
					new rand1 = random(sizeof(TEAM1Spawns));
					SetPlayerPos(playerid, TEAM1Spawns[rand1][0], TEAM1Spawns[rand1][1], TEAM1Spawns[rand1][2]);
					SetPlayerFacingAngle(playerid,270);
					SetCameraBehindPlayer(playerid);
					DM[playerid] = 1;
					}
					else if (1count >= 2count)
					{
					SetPlayerTeam(playerid,TEAM_2);
					new rand2 = random(sizeof(TEAM2Spawns));
					SetPlayerPos(playerid, TEAM2Spawns[rand2][0], TEAM2Spawns[rand2][1], TEAM2Spawns[rand2][2]);
					SetPlayerFacingAngle(playerid,270);
					SetCameraBehindPlayer(playerid);
					DM[playerid] = 1;
					}
					else if (1count == 2count)
					{
					SetPlayerTeam(playerid, RandomTeamJoin[random(sizeof(RandomTeamJoin))]);
					DM[playerid] = 1;
					}

					if(GetPlayerTeam(playerid) == TEAM_1)
					{
				 	1count++;
					new rand1 = random(sizeof(TEAM1Spawns));
					SetPlayerPos(playerid, TEAM1Spawns[rand1][0], TEAM1Spawns[rand1][1], TEAM1Spawns[rand1][2]);
					SetPlayerFacingAngle(playerid,270);
					SetCameraBehindPlayer(playerid);
					SendClientMessage(playerid,COLOR_BLUE, "You have joined the DeathMatch on Team 1!");
					}

					else if(GetPlayerTeam(playerid) == TEAM_2)
					{
					2count++;
					new rand2 = random(sizeof(TEAM2Spawns));
					SetPlayerPos(playerid, TEAM2Spawns[rand2][0], TEAM2Spawns[rand2][1], TEAM2Spawns[rand2][2]);
					SetPlayerFacingAngle(playerid,270);
					SetCameraBehindPlayer(playerid);
					SendClientMessage(playerid,COLOR_RED, "You have joined the DeathMatch on Team 2!");
				 	return 1;
					}
					else if(DM[playerid] == 1)
					{
					SendClientMessage(playerid,COLOR_RED, "You are already in a team!");
					}
					return 1;
					}

			if(listitem == 1) // Points
			{
				ShowPlayerDialog(playerid, DIALOGID+1, DIALOG_STYLE_INPUT, "Points", "Points", "Select", "Back");
			}
			if(listitem == 2) // Information
			{
				ShowPlayerDialog(playerid, DIALOGID+2, DIALOG_STYLE_MSGBOX, "DeathMatch","mytext", "Ok", "Cancel");
			}
		}
		return 1;
	}

	if(dialogid == DIALOGID+1) // points
	{
	new s[128];
	format(s,sizeof(s),"Points: %i\n\nCost: %i$",PointsQuantity,gCheckout[playerid]);
	ShowPlayerDialog(playerid, DIALOGID+3,0,"Points",s,"Buy","Back");
	}
	else if(dialogid == DIALOGID+2) // info
	{
	return 1;
 }
	else if(dialogid == DIALOGID+3 && CurrMoney >= gCheckout[playerid]) // Buy points
	{
  new PointsStringbought[128];
	format(PointsStringbought,sizeof(PointsStringbought),"You have bought %i Points for $%i",PointsQuantity,gCheckout[playerid]);
	GivePlayerMoney(playerid,-gCheckout[playerid]);
 	PInfo[playerid][Points] = PInfo[playerid][Points]+PointsQuantity;
 	ShowPlayerDialog(playerid, DIALOGID, DIALOG_STYLE_LIST, "Master", "Enter DeathMatch\nBuy Points\nInformation", "Select", "Cancel");
 	return 1;
  }
  else if(dialogid == DIALOGID+3 && CurrMoney <= gCheckout[playerid]) // Buy points
  {
	  SendClientMessage(playerid,COLOR_BLUE,"You do not have enough money.");
	  ShowPlayerDialog(playerid, DIALOGID, DIALOG_STYLE_LIST, "Master", "Enter DeathMatch\nBuy Points\nInformation", "Select", "Cancel");
		return 1;
	 	}
	return 0;
 }
it just fking wont work for me. i dont understand the freaking scripts.....
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)