12.09.2014, 15:53
(
Последний раз редактировалось Manyula; 15.10.2014 в 14:18.
)
Interactive Dialogs
[ame="http://www.youtube.com/watch?v=QLYC6-zMjNo"]http://www.youtube.com/watch?v=QLYC6-zMjNo[/ame]
Hello folks!I would like to share this great tutorial on interactive dialogs, meaning that you can add or remove listitems of a
dialog while it is being shown to one or more players, making it look like the dialog updates its items. I found this
tutorial here, and I thought I translate it for you guys. I do not take credit for any of this. This is a tutorial created
by a guy named Jeffry on the German SA:MP board. You can find the original text here.
Short Overview
You might wonder what this is good for. It’s simple – with a few methodical steps, neat little functions and enough
working effort you will be able to create a dialog that updates its content on occasions you want it to update! Of
course, it’s up to you to choose where or how exactly to implement it. This is merely a general tutorial on how this
whole stuff works. In fact, we won’t be using any timers in this tutorial, making it even more efficient. Move along,
and you will see!
Let’s go through the code!
Step 1 – Variables
First thing’s first – variables. In order for us to later be able to know which player has currently opened a dialog, we
need to declare a global variable for all players. And let’s set the variable’s value straight to -1 to avoid mistakes.
pawn Код:
new DialogOpened[MAX_PLAYERS] = {-1,…};
repeating code blocks, keeping the code shorter and giving us a much better overview.
First, we define a constant that determines the maximum amount of dialogs being used in your gamemode (it’s really
up to you to set this value).
pawn Код:
#define MAX_DIALOGS 100
pawn Код:
new Caption[MAX_DIALOGS][36];
new Info[MAX_DIALOGS][256];
new Button1[MAX_DIALOGS][8];
new Button2[MAX_DIALOGS][8];
These little functions ensure that we can easily handle our dialogs. Since we are talking about dialogs, we need to
modify ShowPlayerDialog a little bit.
pawn Код:
stock ShowUpdateDialog(playerid, dialogid, style, caption[], info[], button1[], button2[])
{
//This simply states that the player (playerid) has opened a certain dialog (dialogid).
DialogOpened[playerid] = dialogid;
//Next, we just go ahead and show the player the dialog like we are used to.
ShowPlayerDialog(playerid, dialogid, style, caption, info, button1, button2);
//If an existing dialog has been opened, the according data shown in the dialog will be saved in our global
//variables.
if(dialogid > -1 && dialogid < MAX_DIALOGS)
{
format(Caption[dialogid], sizeof(Caption[]), caption);
format(Info[dialogid], sizeof(Info[]), info);
format(Button1[dialogid], sizeof(Button1[]), button1);
format(Button2[dialogid], sizeof(Button2[]), button2);
}
return 1;
}
pawn Код:
stock GetPlayerDialog(playerid)
{
return DialogOpened[playerid];
}
stock GetDialogCaption(dialogid) return Caption[dialogid];
stock GetDialogInfo(dialogid) return Info[dialogid];
stock GetDialogButton1(dialogid) return Button1[dialogid];
stock GetDialogButton2(dialogid) return Button2[dialogid];
//And to make life a tad bit easier, let’s also add this one.
stock PlayerName(playerid)
{
new pName[MAX_PLAYER_NAME];
GetPlayerName(playerid, pName, sizeof(pName));
return pName;
}
This is an essential part of this whole tutorial. Let’s begin with adding items to a dialog. We create the function
"AddItemToDialog” by passing the dialogid and the text of the listitem. In order to make sure that we are not facing
any troubles, we check whether the same item is already in the list. If so it gets removed and again added.
pawn Код:
stock AddItemToDialog(dialogid, item[])
{
//We search the item.
new ItemPosition = strfind(Info[dialogid], item);
//If the item has been found, it will be deleted.
if(ItemPosition != -1) strdel(Info[dialogid], ItemPosition, ItemPosition(item) + strlen(item) + 1);
//Afterwards, the item will be added to the list.
format(Info[dialogid], sizeof(Info[]), “%s%s\n”, Info[dialogid], item);
//We finish the function by updating the dialog for all players.
return UpdateDialogForAll(dialogid);
}
pawn Код:
stock RemoveItemFromDialog(dialogid, item[])
{
//We search the item.
new ItemPosition = strfind(Info[dialogid], item);
//If the item has not been found, nothing will be done.
if(ItemPosition == -1) return 0;
//Else it will be removed.
strdel(Info[dialogid], ItemPosition, ItemPosition + strlen(item) + 1);
//Again, we finish the function by updating the dialog for all players.
return UpdateDialogForAll(dialogid);
}
pawn Код:
stock UpdateDialogForAll(dialogid)
{
//We do a loop through all players (i)
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(DialogOpened[i] == dialogid) //If the player has currently opened an edited/updated dialog…
{
//…we simply show it to him again with the new updated content.
ShowPlayerDialog(i, DialogOpened[i], DIALOG_STYLE_LIST, Caption[DialogOpened[i]], Info[DialogOpened[i]], Button1[DialogOpened[i]], Button2[DialogOpened[i]]);
}
}
return 1;
}
What does it do? It calls the info text (global variable “Info”) from the dialogid (DialogOpened) the player has
opened.
There is one more function we need for our system. We want to have a function that returns an item on the basis of
a listitem from OnDialogResponse. We simply need to count the word wraps (\n). If the right amount has been found
(=listitem), the string will be splitted and the item will be returned.
pawn Код:
stock GetItemFromDialog(dialogid, listitem)
{
new string[64], count, lastpos = -1, tmp[sizeof(Info[])];
for(new i = 0; i < strlen(Info[dialogid]); i++)
{
if(Info[dialogid][i] == '\n')
{
if(count == listitem)
{
tmp = Info[dialogid];
strdel(tmp, i, strlen(Info[dialogid]));
strdel(tmp, 0, lastpos + 1);
break;
}
count++;
lastpos = i;
}
}
format(string, sizeof(string), tmp);
return string;
}
Phew, we’re almost there! Let’s take a look at the callbacks we need to feed with some code!
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
//We set the value of the player’s variable to -1 since a disconnected player can’t have a dialog opened.
DialogOpened[playerid] = -1;
return 1;
}
pawn Код:
COMMAND:showlist(playerid, params[])
{
//If the length of the info text equals 0, then there are no items listed.
if(!strlen(GetDialogInfo(0))) return SendClientMessage(playerid, -1, “Nobody is listed in this dialog.”);
//Else, the dialog will be shown to the player.
ShowUpdateDialog(playerid, 0, DIALOG_STYLE_LIST, “Example”, GetDialogInfo(0), “OK”, “Cancel”);
}
COMMAND:additem(playerid, params[])
{
//We add our name to the list with the ID 0.
AddItemToDialog(0, PlayerName(playerid));
return 1;
}
COMMAND:removeitem(playerid, params[])
{
//We remove our name from the list with the ID 0.
RemoveItemFromDialog(0, PlayerName(playerid));
return 1;
}
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
//If the player selects something the dialog will always be closed. So we set our value to -1 since after closing a dialog it is not opened anymore.
DialogOpened[playerid] = -1;
//Here, we check whether the dialogid is 0 and whether the first button (button1) has been pressed.
if(dialogid == 0 && response == 1)
{
//We search for the player ID on the basis of the name that has been entered in the list.
new item[64], founded = -1;
//We return the name on the basis of the listitem using the following function:
item = GetItemFromDialog(dialogid, listitem);
//If a wrong listitem has been passed, an error message will be sent.
if(!strlen(item)) return SendClientMessage(playerid, -1, “ERROR: Item could not be found.”);
//Eventually, we search for the name of the player.
for(new = 0; i < MAX_PLAYERS; i++)
{
if(IsPlayerConnected(i) && !strcmp(PlayerName(i), item))
{
//If the name has been found, it will be saved to our variable and the loop will be stopped.
foundid = i;
break;
}
}
//Now, we can do whatever we want, but let’s just stick to a simple client message.
new string[150];
format(string, sizeof(string), “INFO: I have clicked %s with the ID %d.”, PlayerName(foundid), foundid);
return SendClientMessage(playerid, -1, string);
}
return 0;
}
Please inform me about errors of any kind. I will fix them if necessary.
------------------------------------------------------------------
Edit1: Typo.
Edit2: Typo & added a sample video.
Edit3: Code fixes.
Edit4: Code fixes again. It should be fully functional now.