-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdialog.inc
283 lines (231 loc) · 8.39 KB
/
dialog.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#if defined _INC_dialog
#endinput
#endif
#define _INC_dialog
/**
* <library name="dialog" summary="Include for dialog">
* <license>
* (c) Copyright 2024, shierru (Nikita).
* </license>
* <summary pawndoc="true">
* This library uses the enhanced <em>pawndoc.xsl</em> from
* <a href="https://github.com/pawn-lang/pawndoc">pawn-lang/pawndoc</a>.
* This XSL has features such as library and markdown support, and will not
* render this message when used.
* </summary>
* </library>
*/
/// <p/>
#pragma tabsize 4
/**
* <library>dialog</library>
*/
#if !defined DEFAULT_DIALOG_ID
#define DEFAULT_DIALOG_ID (32000)
#endif
/**
* <library>dialog</library>
*/
#if !defined MAX_DIALOG_FUNCTION
#define MAX_DIALOG_FUNCTION (__namemax)
#endif
/**
* <library>dialog</library>
*/
#if !defined isnull
#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#endif
/**
* <library>dialog</library>
*/
#define DialogCreate:%0(%1) forward @D_CREATE_%0(%1);public @D_CREATE_%0(%1)
#define DialogResponse:%0(%1) forward @D_RESPONSE_%0(%1);public @D_RESPONSE_%0(%1)
#define DialogInterrupt:%0(%1) forward @D_INTERRUPT_%0(%1);public @D_INTERRUPT_%0(%1)
#define Dialog: #
/**
* <library>dialog</library>
*/
#if !defined CHAIN_ORDER
#define CHAIN_ORDER() 0
#endif
#define CHAIN_HOOK(%0) forward @CO_%0();public @CO_%0(){return CHAIN_ORDER()+1;}
#define CHAIN_NEXT(%0) @CO_%0
#define CHAIN_FORWARD:%0_%2(%1)=%3; \
forward %0_%2(%1); \
public %0_%2(%1) <_ALS : _ALS_x0, _ALS : _ALS_x1> { return (%3); } \
public %0_%2(%1) <> { return (%3); }
#define CHAIN_PUBLIC:%0(%1) %0(%1) <_ALS : _ALS_go>
CHAIN_HOOK(DIALOG)
#undef CHAIN_ORDER
#define CHAIN_ORDER CHAIN_NEXT(DIALOG)
static stock _DIALOG_IncludeStates() <_ALS : _ALS_x0, _ALS : _ALS_x1, _ALS : _ALS_x2, _ALS : _ALS_x3> {}
static stock _DIALOG_IncludeStates() <_ALS : _ALS_go> {}
/**
* <library>dialog</library>
* <summary>Call Types</summary>
*/
enum DIALOG_CALL_TYPES
{
DIALOG_CALL_TYPE_UNKNOWN = -1,
DIALOG_CALL_TYPE_NONE,
DIALOG_CALL_TYPE_CREATE,
DIALOG_CALL_TYPE_RESPONSE,
DIALOG_CALL_TYPE_INTERRUPT
};
#define MAX_DIALOG_CALL_TYPES (DIALOG_CALL_TYPES)
#define DIALOG_CALL_TYPE_UNKNOWN (DIALOG_CALL_TYPES:-1)
#define DIALOG_CALL_TYPE_NONE (DIALOG_CALL_TYPES:0)
#define DIALOG_CALL_TYPE_CREATE (DIALOG_CALL_TYPES:1)
#define DIALOG_CALL_TYPE_RESPONSE (DIALOG_CALL_TYPES:2)
#define DIALOG_CALL_TYPE_INTERRUPT (DIALOG_CALL_TYPES:3)
/**
* <library>dialog</library>
* <summary>Static variables</summary>
*/
static
s_PlayerAddress[MAX_PLAYERS][MAX_DIALOG_CALL_TYPES] = {cellmin, ...},
s_PlayerAddressDefault[MAX_DIALOG_CALL_TYPES] = {cellmin, ...};
static s_PlayerFuncName[MAX_PLAYERS][MAX_DIALOG_FUNCTION] = {"", ...};
static bool:s_IsPlayerOpenDialog[MAX_PLAYERS] = {false, ...};
/**
* <library>dialog</library>
* <summary>Show the player a "create" dialog.</summary>
* <param name="playerid">The identifier of the player you want to show the dialog from</param>
* <param name="func">The name of the dialog to show to the player</param>
*/
stock bool:Dialog_Show(playerid, const func[], va_args<>)
{
Dialog_Process(playerid, func, DIALOG_CALL_TYPE_CREATE);
if(YSI_CheckNumargs__(2))
Dialog_Call(playerid, DIALOG_CALL_TYPE_CREATE, playerid);
else
Dialog_Call(playerid, DIALOG_CALL_TYPE_CREATE, playerid, va_start<2>);
return true;
}
/**
* <library>dialog</library>
* <summary>Show the player a dialog.</summary>
* <param name="playerid">The identifier of the player you want to show the dialog from</param>
* <param name="func">The name of the dialog to show to the player</param>
* <param name="style">The style of the dialog</param>
* <param name="title">The title at the top of the dialog. The length of the title can not exceed
* more than 64 characters before it starts to cut off</param>
* <param name="body">The text to display in the main dialog. Use <b><c>\n</c></b> to start a new line
* and <b><c>\t</c></b> to tabulate. May be optionally formatted.</param>
* <param name="button1">The text on the left button</param>
* <param name="button2">The text on the right button. Leave it blank ( "" ) to hide it</param>
*/
stock bool:Dialog_Open(playerid, const func[], const DIALOG_STYLE:style, const caption[], const body[], const button1[], const button2[])
{
memcpy(s_PlayerFuncName[playerid], func, 0, (strlen(func) * cellbytes));
// Let's try to get the addresses of Response and Interrupt functions and memorize them.
Dialog_Process(playerid, func, DIALOG_CALL_TYPE_RESPONSE);
Dialog_Process(playerid, func, DIALOG_CALL_TYPE_INTERRUPT);
return ShowPlayerDialog(playerid, DEFAULT_DIALOG_ID, style, caption, body, button1, button2);
}
/**
* <library>dialog</library>
* <summary>Check if the player has a dialog open.</summary>
* <param name="playerid">Identifier of the player for whom you want to check</param>
* <param name="func">The name of dialog</param>
*/
stock bool:Dialog_IsOpen(playerid, const func[] = "")
{
if(isnull(func))
return s_IsPlayerOpenDialog[playerid];
return !strcmp(s_PlayerFuncName[playerid], func);
}
/**
* <library>dialog</library>
* <summary>Close the dialog to the player.</summary>
* <param name="playerid">The identifier of the player you want to close the dialog from</param>
*/
stock bool:Dialog_Close(playerid)
{
if(!Dialog_IsOpen(playerid))
return false;
// Call the Interrupt function
Dialog_Call(playerid, DIALOG_CALL_TYPE_INTERRUPT, playerid);
s_PlayerAddress[playerid] = s_PlayerAddressDefault;
s_IsPlayerOpenDialog[playerid] = false;
#if defined HidePlayerDialog
return HidePlayerDialog(playerid);
#else
return ShowPlayerDialog(playerid, -1, DIALOG_STYLE_MSGBOX, " ", " ", " ", "");
#endif
}
// Static func's
static stock void:Dialog_Process(playerid, const func[], DIALOG_CALL_TYPES:calltype)
{
if(isnull(func))
return;
new name[MAX_DIALOG_FUNCTION];
switch(calltype)
{
case DIALOG_CALL_TYPE_CREATE:
strcat(name, "@D_CREATE_");
case DIALOG_CALL_TYPE_RESPONSE:
strcat(name, "@D_RESPONSE_");
case DIALOG_CALL_TYPE_INTERRUPT:
strcat(name, "@D_INTERRUPT_");
default: { return; }
}
strcat(name, func);
s_PlayerAddress[playerid][calltype] = GetPublicAddressFromIndex(funcidx(name));
}
static stock bool:Dialog_IsAddresValid(playerid, DIALOG_CALL_TYPES:calltype)
{
return (s_PlayerAddress[playerid][calltype] != cellmin ? true : false);
}
static stock void:Dialog_Call(playerid, DIALOG_CALL_TYPES:calltype, va_args<>)
{
if(!Dialog_IsAddresValid(playerid, calltype))
return;
if(YSI_CheckNumargs__(2))
CallFunction(s_PlayerAddress[playerid][calltype]);
else
CallFunction(s_PlayerAddress[playerid][calltype], va_start<2>);
}
// Hook's
stock Dialog_ShowPlayerDialog(playerid, dialogid, DIALOG_STYLE:style, const title[], const body[], const button1[], const button2[])
{
if(dialogid != DEFAULT_DIALOG_ID)
return 0;
s_IsPlayerOpenDialog[playerid] = true;
return Dialog_ShowPlayerDialog(playerid, dialogid, style, title, body, button1, button2);
}
#if defined _ALS_ShowPlayerDialog
#undef ShowPlayerDialog
#else
#define _ALS_ShowPlayerDialog
#endif
#define ShowPlayerDialog Dialog_ShowPlayerDialog
// Callback's
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid != DEFAULT_DIALOG_ID)
return 0;
Dialog_Call(playerid, DIALOG_CALL_TYPE_RESPONSE, playerid, response, listitem, ref(inputtext));
return Dialog_OnDialogResponse(playerid, dialogid, response, listitem, inputtext);
}
#if defined _ALS_OnDialogResponse
#undef OnDialogResponse
#else
#define _ALS_OnDialogResponse
#endif
#define OnDialogResponse(%0) CHAIN_PUBLIC:Dialog_OnDialogResponse(%0)
CHAIN_FORWARD:Dialog_OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) = 1;
public OnPlayerDisconnect(playerid, reason)
{
s_PlayerAddress[playerid] = s_PlayerAddressDefault;
s_PlayerFuncName[playerid][0] = '\0';
s_IsPlayerOpenDialog[playerid] = false;
return Dialog_OnPlayerDisconnect(playerid, reason);
}
#if defined _ALS_OnPlayerDisconnect
#undef OnPlayerDisconnect
#else
#define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect(%0) CHAIN_PUBLIC:Dialog_OnPlayerDisconnect(%0)
CHAIN_FORWARD:Dialog_OnPlayerDisconnect(playerid, reason) = 1;