PDA

Просмотр полной версии : [Урок] Пишем команды с DmX [DC_CMD + SSCANF]



DmX
10.02.2014, 23:23
Добрый день уважаемые обитатели Pro-Pawn.ru это мой второй урок посвященный pawn программированию, сегодня я буду учить вас писать команды на DC_CMD + SSCANF.

DC_CMD - достаточно простой командный процессор в pawn программировании. Для меня он более удобный и интересный.

Многие скачивая мод с командным процессором DC_CMD хватались за голову, так как не могли понять как с ним работать, а привыкли к RLS командам(тупому быдло коду).

(!)Команды построены на проверках.

Вот дана команда выдачи выдачи жизней:



CMD:sethp(playerid, params[])
{
new str[24];
if(sscanf(params,"ui",params[0],params[1])) return SendClientMessage(playerid, COLOR_WHITE,"Используйте: /sethp [id] [кол-во жизней]");
if(params[1] < 0 || params[1] > 100) return SendClientMessage(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
SetHealth(params[0],params[1]);
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[params[0]][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
return true;
}

Разберем подробнее код:


if(sscanf(params,"ui",params[0],params[1]))
/* Это даем значения, если u - ид/имя игрока если i - число, и даем им значение params[0], params[1] все по порядку*/


SetHealth(params[0],params[1]);
/*Опять же, params[0] - это ид игрока или имя которое мы ввели в команде, а params[1] это наше числовое значение i которое мы ввели когда прописывали команду.*/


if(params[1] < 0 || params[1] > 100)

/*Это действие выводится когда вы ввели значение i - то есть params[1] меньше нуля либо больше 100*/


format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
/* PlayerInfo[playerid][pName] где playerid - ид или имя игрока который прописал команду, params[1] - это опять же наше значение i


SendClientMessage(params[0],COLOR_WHITE, str);
/* Функция показывает сообщение в чат, а кому??? опять же params[0] ( то есть кому дали вы жизни - u )



Табличка значений SSCANF:

u - id или имя игрока
I - целое число
d - целое число
s - строка
f - число с плавающей точкой т.е. дробь

P.S: Если указываете значение "s" указывайте его вот так "s[24]" то есть добавляйте стринг, так как у многих новичков с этим проблема, потом сервер выдает варнинги.

Думаю все прекрасно и понятно написано. Специально для Pro-Pawn.ru

Задавайте вопросы в теме.

Автор: Siman aka DmX

L0ndl3m
10.02.2014, 23:25
ZCMD заменить на DC_CMD и урок будет конфеткой. :3

Salvacore
10.02.2014, 23:27
ZCMD заменить на DC_CMD и урок будет конфеткой. :3
Пропаганда значит:D

DmX
10.02.2014, 23:29
ZCMD заменить на DC_CMD и урок будет конфеткой. :3

Сделано :)

DeimoS
11.02.2014, 05:11
ZCMD заменить на DC_CMD и урок будет конфеткой. :3

Вот это уже отстой :с Всюду пропихиваете свой DC_CMD. Тут не форум пиара командного процессора, а форум помощи скриптерам. Всё же стоит каждому дать шанс на свой выбор :) Лучше уж в теме приписку сделал бы, что команды за DC_CMD и команды на ZCMD создаются подобным образом. Вот, например, как я стал в последнее время обрабатывать команды

public OnPlayerCommandText(playerid, cmdtext[])
{
new cmd[128], params[128], var[5][30];
sscanf(cmdtext, "s[128]s[128]", cmd, params);
if(Command(cmd,"/pay") || Command(cmd,"/givecash") || Command(cmd,"/дать"))
{
if(sscanf(params,"dd", var[0][0],var[0][1])) return SendClientMessage(playerid, 0x00FF00FF, "Помощьник: {FFFFFF}/pay <id> <сумма>");
//Остальной код
return 1;
}

else if(Command(cmd,"/pm") || Command(cmd,"/лс") || Command(cmd,"/личка"))
{
new varstring[129];
if(sscanf(params,"ds[128]", var[0][0],varstring)) return SendClientMessage(playerid, 0x00FF00FF, "Помощьник: {FFFFFF}/pm <id> <сообщение>");
//Остальной код
return 1;
}
return 0;
}
И код приятен глазу/лёгок в написании, и в скорости особо не теряю, ибо команд не так много использую. А если и буду терять, потери должны быть незаметными практически

P.S. Command - макрос, упрощающий написание команды (strcmp заменяет)

semen7907
11.02.2014, 14:15
А как сделать проверку на не существующего игрока?


CMD:sethp(playerid, params[])
{
new str[24];
if(sscanf(params,"ui",params[0],params[1])) return SendClientMessage(playerid, COLOR_WHITE,"Используйте: /sethp [id] [кол-во жизней]");
if(params[1] < 0 || params[1] > 100) return SendClientMessage(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
SetHealth(params[0],params[1]);
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
return true;

DeimoS
11.02.2014, 15:42
if(!IsPlayerConnected(/*переменная, хранящая ID игрока*/)) return SendClientMessage(playerid, 0xFF0000FF, "Такого игрока нет в сети");
В твоём случае так

CMD:sethp(playerid, params[])
{
new str[24];
if(sscanf(params,"ui",params[0],params[1])) return SendClientMessage(playerid, COLOR_WHITE,"Используйте: /sethp [id] [кол-во жизней]");
if(!IsPlayerConnected(params[0])) return SendClientMessage(playerid, 0xFF0000FF, "Такого игрока нет в сети");
if(params[1] < 0 || params[1] > 100) return SendClientMessage(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
SetHealth(params[0],params[1]);
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
return true;
}

MR_BEN
11.02.2014, 17:27
Ребят, кто может объяснить разницу между i и d из таблицы значений SSCANF. Ведь, по сути, они обозначают целое число, тогда смысл их разделять?

DeimoS
11.02.2014, 17:57
Ребят, кто может объяснить разницу между i и d из таблицы значений SSCANF. Ведь, по сути, они обозначают целое число, тогда смысл их разделять?

http://wiki.sa-mp.com/wiki/%D0%94%D1%80%D1%83%D0%B3%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B8%D0%BD%D0%B3%D0%B0#format

Skuba_Lo
04.03.2014, 14:55
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
Вот это сообщение выводится игроку которому дали хп, а как сделать чтобы сообщение еще и выводилось администратору который дал хп, например "Вы установили %такомуто игроку %столько то жизней"?

Seregamil
04.03.2014, 15:17
if(sscanf(params,"ui",params[0],params[1])) return SendClientMessage(playerid, COLOR_WHITE,"Используйте: /sethp [id] [кол-во жизней]");
if(params[1] < 0 || params[1] > 100) return SendClientMessage(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
SetHealth(params[0],params[1]);
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
Я пока тебе просто выделил.

Копюшон
07.03.2014, 11:17
Я пользуюсь Life-CDM он мне удобней, но вижу DC_CDM тоже хоршо, а можете показать скорость команды..

Salvacore
07.03.2014, 16:48
Я пользуюсь Life-CDM он мне удобней, но вижу DC_CDM тоже хоршо, а можете показать скорость команды..

Обновил тест скорости.
http://s3.hostingkartinok.com/uploads/images/2014/03/2ff0f4a62b6024ca39fcc73fff275460.png
Скачать его можно здесь:
http://rghost.ru/52839480

В тест добавлены 2 новых вида команд: стандартные (обозначены, как STD) и на командном процессоре FCMD.
Как видно, стандартные команды (при количестве в 10 штук) работают медленнее остальных. Отрыв особенно заметен в случае, когда у команд есть параметры.



Недавно до меня дошёл миф о том, что если в моде мало команд, то лучше не использовать никаких командных процессоров, якобы стандартные команды будут работать быстрее.
Сейчас мы попробуем доказать или опровергнуть его.

Итак, в скрипте cmdtest.pwn есть макрос PROFILE_ITERS_MINOR, он позволяет указать заданное количество команд для каждого командного процессора.
Изменив его значение на 1 (вместо 10 по умолчанию), можно смоделировать ситуацию, когда в моде всего 1 команда, и измерить быстродействие каждого командного процессора.

Приступим. Ищем в самом начале скрипта строку

#define PROFILE_ITERS_MINOR 10
и заменяем её на

#define PROFILE_ITERS_MINOR 1
Затем компилируем скрипт, запускаем сервер и смотрим на результат.
Для ленивых, выложу то, что получилось у меня:
http://s3.hostingkartinok.com/uploads/images/2014/03/65500e2b3eb6536924cbefe339e88157.png
На данном скриншоте я включил JIT, дабы отсеять лишние вопросы о быстродействии стандартных команд с этим плагином.
Как видно, некоторые командные процессоры действительно начинают работать медленнее, чем стандартные команды. Впрочем, DC_CMD обгоняет по быстродействию стандартные команды в 7 раз, даже всего при 1 команде и с JIT.

Cмотри ;)

underwoker
08.03.2014, 18:54
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
Вот это сообщение выводится игроку которому дали хп, а как сделать чтобы сообщение еще и выводилось администратору который дал хп, например "Вы установили %такомуто игроку %столько то жизней"?


CMD:sethp(playerid, params[])
{
new str[24];
if(sscanf(params,"ui",params[0],params[1])) return SendClientMessage(playerid, COLOR_WHITE,"Используйте: /sethp [id] [кол-во жизней]");
if(!IsPlayerConnected(params[0])) return SendClientMessage(playerid, 0xFF0000FF, "Такого игрока нет в сети");
if(params[1] < 0 || params[1] > 100) return SendClientMessage(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
SetHealth(params[0],params[1]);
format(str,sizeof(str), "%s установил вам жизней %d",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(params[0],COLOR_WHITE, str);
format(str,sizeof(str), "Вы установили %s - %d жизней",PlayerInfo[playerid][pName],params[1]);
SendClientMessage(playerid,COLOR_WHITE, str);
return true;
}

L0ndl3m
08.03.2014, 19:12
format(str,sizeof(str), "Вы установили %s - %d жизней",PlayerInfo[playerid][pName],params[1]);

Может быть params[0]? Так как будет показываться никнейм не игрока которому выдаёшь, а никнейм того игрока, который выдаёт.

DmX
16.03.2014, 09:19
Может быть params[0]? Так как будет показываться никнейм не игрока которому выдаёшь, а никнейм того игрока, который выдаёт.

Правильно , не усмотрел) писал на быструю руку

Alexey_Nikiforov
19.02.2016, 16:14
Размер сриннга следует увеличить.
24 слишком мало.
(24+22+3+1)
24 ник
22 текст
3 максимальное значение 100
1 на нуль символ.

p.s. Как сделать что бы писать целое количество хп а выдавало float

VVWVV
19.02.2016, 16:51
p.s. Как сделать что бы писать целое количество хп а выдавало float


const some_value = 5;
new Float:some_float_variable = float(some_value);

Alexey_Nikiforov
19.02.2016, 17:00
А на примере команды в шапке можно.
Просто не совсем понял как использовать.

VVWVV
19.02.2016, 19:25
А на примере команды в шапке можно.
Просто не совсем понял как использовать.


CMD:test(playerid, params[])
{
new target_id, target_health;
if (sscanf(params, "ui", target_id, target_health))
return 0;
SetPlayerHealth(playerid, float(target_health));
SendClientMessage(playerid, -1, !"+");
return 1;
}

Alexey_Nikiforov
19.02.2016, 19:55
CMD:test(playerid, params[])
{
new target_id, target_health;
if (sscanf(params, "ui", target_id, target_health))
return 0;
SetPlayerHealth(playerid, float(target_health));
SendClientMessage(playerid, -1, !"+");
return 1;
}

Блин читал читал, так и не понял.
target_id создано и не используется.

Можно было просто написать float(params[])
Пока сам методом тырка не дошел не разобрался.
Но все равно спасибо за наводку.
+ бы поставил но нету.

SetPlayerHealth(params[0],float(params[1]));

VVWVV
19.02.2016, 20:10
Блин читал читал, так и не понял.
target_id создано и не используется.

Можно было просто написать float(params[])
Пока сам методом тырка не дошел не разобрался.
Но все равно спасибо за наводку.
+ бы поставил но нету.

SetPlayerHealth(params[0],float(params[1]));

Очевидно же, что переменная target_id должна быть аргументом функции SetPlayerHealth. (Вы можете использовать params, но вот (http://pro-pawn.ru/showthread.php?12988-%D0%9C%D0%B8%D1%84%D1%8B-%D0%BE-Pawn-%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B8%D0%BD%D0%B3%D0%B5-4))
Из этого следует такая команда:

CMD:test(playerid, params[])
{
new target_id, target_health;
if (sscanf(params, "ui", target_id, target_health))
return 0; // Сообщение об ошибке.
if (_:(0 <= target_health <= 100) == 0)
return 0; // Сообщение об ошибке.
if (SetPlayerHealth(target_id, float(target_health)) == 0) // Игрока нет в сети.
return 0; // Сообщение об ошибке.
SendClientMessage(playerid, -1, !"+");
return 1;
}