Unlimited dialogs -
Misiur - 22.08.2013
Introduction
As stated in wiki, the max ID of a dialog is 32767. This is more than enough in most cases, but sometimes you might need to exceed the limit. In other cases you might simply want to group your dialog types. Now - nobody said that the id's can't be reusable.
Defining the dialogs
Let's start with defining dialog groups
pawn Code:
enum e_DIALOG_BASIC {
DIALOG_FOO,
DIALOG_BAR
}
enum e_DIALOG_ADVANCED {
DIALOG_FOOBAR,
DIALOG_BARFOO
}
(notice the small letter in enum label - this causes it to be a
weak tag)
Wrapping ShowPlayerDialog
pawn Code:
stock ShowPlayerDialogEx(playerid, dialogid, style, caption[], info[], button1[], button2[], tagDialogGroup = tagof dialogid) {
switch(tagDialogGroup) {
case (tagof e_DIALOG_ADVANCED): {
state dialogHandler:e_DIALOG_ADVANCED;
}
default: {
state dialogHandler:e_DIALOG_BASIC;
}
}
return ShowPlayerDialog(playerid, dialogid, style, caption, info, button1, button2);
}
Instead of messy switch statement in OnDialogResponse we can harness the power of
automata (which uses same opcodes as switch, but looks fancier and cleaner at the same time). tagDialogGroup will grab tag automatically from dialogid argument and then set the state to the one we need (there is no possibility of assigning variable to state, and conditional state is not optimal in this case).
Adding commands and handlers
pawn Code:
CMD:basic(id, params[]) {
return ShowPlayerDialogEx(id, DIALOG_FOO, DIALOG_STYLE_MSGBOX, "Basic text", "Basic info", "Ok", "Have fun");
}
CMD:adv(id, params[]) {
return ShowPlayerDialogEx(id, DIALOG_FOOBAR, DIALOG_STYLE_MSGBOX, "Adv text", "Adv info", "Ok", "Have fun");
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) <> {
printf("Dialog %d of BASIC", dialogid);
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) <dialogHandler:e_DIALOG_ADVANCED> {
printf("Dialog %d of Advanced", dialogid);
return 1;
}
DIALOG_FOO has e_DIALOG_BASIC tag, and DIALOG_FOOBAR has e_DIALOG_ADVANCED tag. State values are equal to our tags (and e_DIALOG_BASIC is handled as default group). Everything works, let's celebrate! Using only just two groups we can handle up to 65536 dialogs. Whenever you want, you can add another group by adding 3 lines in ShowPlayerDialogEx, another enumerator and additional handler.
God damn it
Just as you are about to open the champagne, sudden realization hits you - we don't have any protection from cheaters and party crashers. That's not good. Usually it's handled by fixes.inc, but now it's not!
Let's fix it
We have two ways of doing this. One would require adding protection in every dialogresponse handler, and the other one requires us to get rid of magic state machines. The second option is easier, and that's what we are going to do. Good bye tidy code!
Fixes.inc is written by people who know pawn inside-out, so we will use it, while adding additional functionality.
pawn Code:
new PlayerDialogGroup[MAX_PLAYERS];
Each player needs to have his current dialog group stored somewhere - earlier we dealt with it using state machines, now we have to do it manually.
pawn Code:
stock ShowPlayerDialogEx(playerid, dialogid, style, caption[], info[], button1[], button2[], tagDialogGroup = tagof dialogid) {
PlayerDialogGroup[playerid] = tagDialogGroup;
return ShowPlayerDialog(playerid, dialogid, style, caption, info, button1, button2);
}
We are assigning the tag of dialogid directly. In fact ShowPlayerDialogEx looks nicer now, and could be transformed into macro
pawn Code:
#define ShowPlayerDialogEx(%1,%2,%3,%4,%5,%6,%7) (PlayerDialogGroup[%1] = tagof(%2), ShowPlayerDialog(%1,%2,%3,%4,%5,%6,%7))
Your choice.
pawn Code:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) {
switch(PlayerDialogGroup[playerid]) {
case (tagof e_DIALOG_ADVANCED): {
printf("Dialog %d of ADVANCED", dialogid);
}
default: {
printf("Dialog %d of BASIC", dialogid);
}
}
return 1;
}
And that's it. We can now use best of both worlds. Your whole additional logic (checking the dialogid, listitem selected, etc.) goes inside specific case. Additionally you can add some actions which will fire up on multiple dialog groups, or all of them.
That's all folks!
Re: Unlimited dialogs -
theYiin - 22.08.2013
pretty nice. But why not
Code:
new p_currentDialog[MAX_PLAYERS];
enum eDialogs
{
dRegistration,
dLogin
// ... unlimited ! (technically limited - 2147483647)
};
stock showDialog(playerid, dialogid, type, head[], body[], left[], right[])
{
p_currentDialog[playerid] = dialogid;
ShowPlayerDialog(playerid, 0, type, head, body, left, right);
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
new const id = p_currentDialog[playerid];
p_currentDialog[playerid] = 0;
switch( id )
{
case dRegistration:
{
// do registration things
}
case dLogin:
{
// do login things
}
}
return 0;
}
Re: Unlimited dialogs -
Misiur - 22.08.2013
@Y_Less: Well, in fact enums aren't used there at all. Take a look at this code (not quite valid, but works can be parsed with -a flag)
pawn Code:
enum A {}
enum B {}
main() {
state s:A;
Fnc();
state z:B;
Fnck();
}
Fnc() <s:A> {
#emit STATEA
}
Fnc() <s:B> {
#emit STATEB
}
Fnck() <z:B> {
#emit STATEB
}
Fnck() <z:A> {
#emit STATEA
}
It simply produces
pawn Code:
load.pri 4 ; Fnc
switch 3
l.3 ; 20
casetbl
case 2 0
case 1 1
case 2 2
load.pri 8 ; Fnck
switch 6
l.6 ; 4c
casetbl
case 2 0
case 1 4
case 2 5
They are substituted in order of declaraction with numbers. Even "__" as state name will get parsed, but I can't find official rules for their labels.
@theYiin: Yup, I thought about this version (which is very clever by the way), but then I changed my main goal to grouping (so you don't have to do something like)
pawn Code:
enum g_Main {
d_n_1,
d_n_2,
d_n_3
}
enum g_Additional {
d_a_1 = 3,
d_a_2,
d_a_3
}
Re: Unlimited dialogs -
theYiin - 22.08.2013
Quote:
Originally Posted by Y_Less
Another thought: Given that there are only 1000 players, there can only be 1000 dialogs on display at once maximum, so why not use playerid instead and dispense with dialog IDs entirely?
|
do you mean
http://forum.sa-mp.com/showthread.ph...36#post2667336 ?