Просмотр полной версии : [Вопрос] Как сделать поиск разделителя для команды /todo
gangzone.ini
21.11.2019, 15:05
Возник вопрос по созданию команды /todo , с выводом текста
CMD:todo(playerid, params[])
{
if(sscanf(params, "p<*>s[128]s[64]", params[0], params[1])) return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
// else if(sscanf(params, "%s'*'%s", params[0], params[1])) return SendClientMessage(playerid, COLOR_GREY, !"Используейте символ '*' для разделения. Пример: /todo привет * протянул руку");
totalstring[0] = EOS;
format(totalstring, sizeof(totalstring), " %s {C2A2DA}- сказал(а) %s, %s", params[0], pInfo[playerid][pName], params[1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
Если с проверкой sscanf(params, "%s'*'%s", params[0], params[1] - ничего не происходит
Если без проверки , /todo *a b текст проходит , а нужно /todo a * b , как так сделать ?
Так же , текст не корректно выводиться , например /todo a*b , выводит "ab * b"
Во-первых, твоя команда не будет работать, ибо второй параметр, куда ты записываешь действие, перезапишет первый параметр, куда ты записываешь текст. "params" - это одномерный массив. И когда ты указываешь "params[1]" - это означает, что запись текста в массив начнётся с первой ячейки, а не то, что вдруг появится какой-то отдельный массив и в него запишется текст.
Во-вторых, проще сделать так:
CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';
format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
Ибо и никакие дополнительные массивы вводить не нужно, и возиться с настройками sscanf
gangzone.ini
21.11.2019, 16:21
Во-первых, твоя команда не будет работать, ибо второй параметр, куда ты записываешь действие, перезапишет первый параметр, куда ты записываешь текст. "params" - это одномерный массив. И когда ты указываешь "params[1]" - это означает, что запись текста в массив начнётся с первой ячейки, а не то, что вдруг появится какой-то отдельный массив и в него запишется текст.
Во-вторых, проще сделать так:
CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';
format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
Ибо и никакие дополнительные массивы вводить не нужно, и возиться с настройками sscanf
В любом месте можно поставить *
/todo * a a
В любом месте можно поставить *
/todo * a a
Ну так проверяй размер текста в params и params[find_pos+1].
CMD:todo(playerid, params[])
{
new find_pos = strfind(params, "*");
if(find_pos == -1)
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
params[find_pos] = '\0';
if(!strlen(params) || !strlen(params[find_pos+1]))
return SendClientMessage(playerid, COLOR_WHITE, !" Введите: /todo [текст] * [действие]");
format(totalstring, sizeof(totalstring),
" %s {C2A2DA}- сказал(а) %s, %s", params, pInfo[playerid][pName], params[find_pos+1]);
SendActionMessage(playerid, 0xC8C8C8FF, totalstring, 15.0);
return true;
}
SteveStage
21.11.2019, 16:41
Лично я использую такую конструкцию:
CMD:todo(playerid, params[])
{
new
text[21],
action[31];
if(sscanf(params, "p<*>s[21]s[31]", text, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase]*[action]");
if(text[20] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина реплики в отыгровке фразы с действием: 20 символов!");
if(action[30] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина действия в отыгровке фразы с действием: 30 символов!");
if(strlen(text) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина отыгровки фразы в отыгровке фразы с действием: 2 символа!");
if(strlen(action) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина отыгровки действия в отыгровке фразы с действием: 2 символа!");
static const
fmt_str[] = "'%s' - сказал%s %s, %s";
new
str[sizeof(fmt_str)-6+MAX_PLAYER_NAME+30+20+1+1];
format(str, sizeof(str), fmt_str, text, (player[playerid][pSex] == 1) ? ("") : ("а"), GetName(playerid), action);
ProxDetector(playerid, 20.0, COLOR_ACTION, str);
SetPlayerChatBubble(playerid, str, COLOR_ACTION, 20.0, 4000);
return true;
}
Не знаю насчет оптимизации, но багов с выводом текста не обнаружено
Также такой вариант (многовато переменных)
CMD:todo(playerid, params[])
{
new
text[21],
space[2],
action[31];
if(sscanf(params, "s[21]s[2]s[31]", text, space, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
if(!strcmp(text, "*") || !strcmp(action, "*") || strcmp(space, "*"))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
if(text[20] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина реплики в /todo: 20 символов!");
if(action[30] != EOS)
return SCM(playerid, COLOR_YELLOW, !"Максимальная длина действия в /todo: 30 символов!");
if(strlen(text) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина фразы в /todo: 2 символа!");
if(strlen(action) < 2)
return SCM(playerid, COLOR_YELLOW, !"Минимальная длина действия в /todo: 2 символа!");
static const
fmt_str[] = "'%s' - сказал%s %s, %s";
new
str[sizeof(fmt_str)-6+MAX_PLAYER_NAME+30+20+1+1];
format(str, sizeof(str), fmt_str, text, (player[playerid][pSex] == 1) ? ("") : ("а"), GetName(playerid), action);
ProxDetector(playerid, 20.0, COLOR_ACTION, str);
SetPlayerChatBubble(playerid, str, COLOR_ACTION, 20.0, 4000);
return true;
}
P.S. У последнего варианта есть баг - во фразе и действии нельзя ставить пробелы, иначе способ разделения фразы, действия и * пробелами собъется
Решение к багу 2 варианта - убрать массив space, удалить эту проверку
if(!strcmp(text, "*") || !strcmp(action, "*") || strcmp(space, "*"))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
И заменить
if(sscanf(params, "s[21]s[2]s[31]", text, space, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
на
if(sscanf(params, "s[21]'*'s[31]", text, action))
return SCM(playerid, COLOR_YELLOW, !"Образец отыгровки фразы с действием: /todo [phrase] * [action]");
Я выше уже дал рабочий вариант, который, к тому же, проще и оптимизированнее твоего)
Судя по благодарности под моим постом, автор темы получил ответ на свой вопрос, поэтому закрываю тему.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot