можно отдельный урок для
пожалуйстаЦитата:
3) Как пропустить необязательный параметр?
В Pawn есть возможность создания функций с необязательными параметрами, у которых уже есть значения, задаваемые по умолчанию.
Вид для печати
можно отдельный урок для
пожалуйстаЦитата:
3) Как пропустить необязательный параметр?
В Pawn есть возможность создания функций с необязательными параметрами, у которых уже есть значения, задаваемые по умолчанию.
Открыть папку pawno/include и искать в инклудах знак "=", после этого знака обычно указывают значения аргументов по умолчанию.
Скажу сразу, в SA:MP полно таких функций с необязательными аргументами, но они сделаны только для обратной совместимости скриптов с предыдущими версиями.
Например, в версии 0.2 была функция CreatePickup:
Затем в 0.3a реализовали виртуальные миры и добавили возможность ставить пикапы только в один из таких миров, добавив в CreatePickup параметр virtualworld.PHP код:
native CreatePickup(model, type, Float:X, Float:Y, Float:Z);
Параметр сделан опциональным, поэтому, если попытаться скомпилировать скрипт для сервера версии 0.2, в котором параметр virtualworld не указан, то скрипт скомпилируется и с инклудами версии 0.3a и новее.PHP код:
native CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0);
а что тогда озночает & ?
н-р:PHP код:
native GetPlayerPos(playerid, &Float:x, &Float:y, &Float:z);
ссылка, но на самом деле это "псевдо ссылка"
Код из первого пункта можно на:
Использование:PHP код:
stock min_max_random(min=0, max)
return random(max - min) + min;
#if defined _ALS_random
#undef random
#else
#define _ALS_random
#endif
#define random(%0,%1) min_max_random(%0,%1)
PHP код:
random(10); // 0;10
random(10,20); // 10;20
А что если надо было бы не 1 переменную, а 2 или 3, по очереди так и писать?PHP код:
#define noinit:%0[%1]; goto _noinit_%0;new %0[%1];_noinit_%0:
PHP код:
noinit:str[10];
noinit:strr[20];
noinit:strrr[30];
Через этот макрос есть ли вероятность бага с goto ?
Наблюдаю "странный" баг при использовании макроса
При повторном использовании функции где идет создание массива таким методом, то текст предыдущего использования функции остается, и получается "накладывание" текстов.PHP код:
#define noinit:%0[%1]; goto _noinit_%0;new %0[%1];_noinit_%0:
Возможно ли это из-за того что текст заполняется через strcat?
Тестить не тестил, но помоему и при заполнении через format такая же шляпа.
Может стоит как-то заменить стоковую инициализацию каким-то более быстрым вариантом?
Или всё-же отказаться от "заводской" инициализации при заполнении через strcat...
Кому то просто нужно ближе подобраться к понятию инициализация
Данный приём стоит использовать только тогда, когда массив имеет большое кол-во ячеек.
Ибо инициализация таких объемных наборов данных занимает достаточно продолжительное время, особенно в тех массивах, кои занимают по 1500-2000 байт и выше.
Применять оператор goto, или отправлять инструкцию jump, в местах, например, где необходимо проинициализировать массив, заточенный под форматирование - бессмысленно.
Так и не решился создавать отдельную тему, так что отпишу сюда.
Очень часто в чужих скриптах вижу, как один и тот же диалог повторяется в нескольких местах. Это мало того, что потребляет лишнюю память, так ещё и доставляет трудности в случае, если вдруг захочется изменить текст этого диалога (да, можно пользоваться автозаменой, но я хочу предложить альтернативу, которая и уменьшит потребление памяти, и не заставит мучиться с автозаменой).
А если это целая система, построенная на диалогах - всё становится ещё страшнее, ибо переплетение в виде кучи вызовов разных диалогов напрочь убивает читаемость.
В общем-то, думаю, ни для кого не секрет, что повторяющийся код лучше убирать в отдельную функцию и вызывать уже функцию, а не каждый раз прописывать код. И как раз именно это я предлагаю использовать. Только если в случае с одним конкретным диалогом всё, вроде как, понятно, то когда у вас целая система, построенная на диалогах, создавать для каждого диалога свою функцию тоже не очень удобно, ибо придётся помнить кучу ненужных названий. Собственно, я хочу предложить решение (точнее, просто натолкнуть на эту идею тех, кто сам до неё не дошёл) для подобных ситуаций. Заключается оно в том, что для одной конкретной системы будет использоваться одна функция, через которую уже будут показываться все диалоги этой системы. В общем-то реализация проста:
И уже просто в том месте, где нужно (повторно) показать диалог, прописываем:PHP код:
stock ShowRegistrationDialog(playerid, dialogid)
{
switch(dialogid)
{
case id_диалога_1:
{
ShowPlayerDialog(playerid, dialogid, прочая_информация);
}
case id_диалога_2:
{
//Тут любой код, что требуется выполнять при каждом показе диалога
ShowPlayerDialog(playerid, dialogid, прочая_информация);
}
case id_диалога_3:
{
ShowPlayerDialog(playerid, /*тут можно именно dialogid и указывать, ибо там в любом случае будет хранится нужный ID диалога, если условие в switch сработает*/, прочая_информация);
}
}
return 1;
}
Всё это и код в более опрятный вид приводит, ибо нет строк, что за границы экрана уходят, и позволяют без проблем вызывать диалоги там, где это требуется, без каких-либо копирований целого диалога.PHP код:
ShowRegistrationDialog(playerid, id_диалога_1);
Только стоит обязательно учитывать, что не стоит в одну такую функцию пихать кучу диалогов, ибо это будет, опять же, неудобно. Лучше, как я писал выше, для каждой системы выделять одну функцию.
И если использовать перечисление для хранения ID диалогов, то код становится ещё опрятнее:
Собственно, всё. Вроде, вполне логичное оформление кода, но, судя по коду в паблике, практически никто не доходит до использования подобного.PHP код:
enum
{
dRegisterMain,
dRegisterInputName,
dRegisterInputPass
}
stock ShowRegistrationDialog(playerid, dialogid)
{
switch(dialogid)
{
case dRegisterMain:
{
ShowPlayerDialog(playerid, dialogid, прочая_информация);
}
case dRegisterInputName:
{
//Тут любой код, что требуется выполнять при каждом показе диалога
ShowPlayerDialog(playerid, dialogid, прочая_информация);
}
case dRegisterInputPass:
{
ShowPlayerDialog(playerid, /*тут можно именно dialogid и указывать, ибо там в любом случае будет хранится нужный ID диалога, если условие в switch сработает*/, прочая_информация);
}
}
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case dRegisterMain:
{
if(!response)
return 1;
else
return ShowRegistrationDialog(playerid, dRegisterInputName);
}
case dRegisterInputName:
{
if(!response)
return ShowRegistrationDialog(playerid, dRegisterMain);
else
return ShowRegistrationDialog(playerid, dRegisterInputPass);
}
case dRegisterInputName:
{
if(!response)
return ShowRegistrationDialog(playerid, dRegisterInputName);
else
return SpawnPlayer(playerid);
}
}
}
Для подобных случаев есть: TDW Dialog Library
Ну, во-первых, знания о том, как такое можно реализовать, лишними не будут никогда. Слепое пользование чужим инструментом часто приводит к тому, что пользователь не может решить, казалось бы, простые проблемы, связанные с этим инструментом.
Во-вторых, изучать синтаксис целой библиотеки (который, к слову, далеко не самый удачный, как по мне) ради подобного - не самое лучшее распределение собственного времени =)
Использую самописанную библиотеку для тех же целей, похожую на версию от Стяжкина (то бишь, синтаксис максимально приближен к синтаксису оригинальных функций), но это не помешало написать мне тот пост :) У каждого свои предпочтения и, как можно заметить, большинство предпочитает не пользоваться какими-то сторонними библиотеками для обработки диалогов. И моя информация именно для них