PDA

Просмотр полной версии : [CMD] /do



Иван Бубнов
13.03.2016, 21:15
Предназначение команды думаю объяснять не нужно. Баян в моем исполнении.


CMD:do(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX, Float:PosY, Float:PosZ, world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1 char];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

strcat(string, params);
strcat(string, " (");
strcat(string, name);
strcat(string, ")");

new
iter = GetPlayerPoolSize();
#if defined foreach
foreach(new i : Player)
{
#else
#if defined GetPlayerPoolSize
for(new i = -1; ++i != iter;)
#else
for(new i = -1; ++i != MAX_PLAYERS;)
#endif
#endif
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}



Автор: Иван Бубнов (http://pro-pawn.ru/member.php?4759-%D0%98%D0%B2%D0%B0%D0%BD-%D0%91%D1%83%D0%B1%D0%BD%D0%BE%D0%B2)
Специально для Pro-Pawn.Ru (pro-pawn.ru)
Копирование данной статьи на других ресурсах без разрешения автора запрещено!
Спасибо всем за советы по коду!

DeimoS
13.03.2016, 21:25
Вот эту проверку

if(0 == IsPlayerConnected(i))
continue;
тоже стоит внести в "#if defined foreach ", не? Точнее, в "#if !defined foreach "

Иван Бубнов
13.03.2016, 21:27
Вот эту проверку

if(0 == IsPlayerConnected(i))
continue;
тоже стоит внести в "#if defined foreach ", не? Точнее, в "#if !defined foreach "

Не додумался чет :good:

DeimoS
13.03.2016, 21:27
Как-то так, короч

CMD:do(playerid, params[])
{
if(isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX,
Float:PosY,
Float:PosZ,
string[144 + 1 + (-2 + MAX_PLAYER_NAME)];
GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, string, sizeof(string));
format(string, sizeof(string), "%s (%s)", params, string);
#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if(0 == IsPlayerConnected(i))
continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ))
continue;
if(GetPlayerVirtualWorld(i) != GetPlayerVirtualWorld(playerid) || GetPlayerInterior(i) != GetPlayerInterior(playerid))
continue;
SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

Иван Бубнов
13.03.2016, 21:30
Как-то так, короч

CMD:do(playerid, params[])
{
if(isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX,
Float:PosY,
Float:PosZ,
string[144 + 1 + (-2 + MAX_PLAYER_NAME)];
GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, string, sizeof(string));
format(string, sizeof(string), "%s (%s)", params, string);
#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if(0 == IsPlayerConnected(i))
continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ))
continue;
if(GetPlayerVirtualWorld(i) != GetPlayerVirtualWorld(playerid) || GetPlayerInterior(i) != GetPlayerInterior(playerid))
continue;
SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

я по другому сделал, шапку апдейт уже, но твой вариант проще

ziggi
13.03.2016, 21:51
Ты ещё кое-что упустил.


CMD:do(playerid, params[])
{
if(isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX,
Float:PosY,
Float:PosZ,
world,
interior,
string[144];
GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, string, sizeof(string));
world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);
format(string, sizeof(string), "%s (%s)", params, string);
#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if(0 == IsPlayerConnected(i) || 0 != IsPlayerNPC(i))
continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ))
continue;
if(GetPlayerVirtualWorld(i) != world || GetPlayerInterior(i) != interior)
continue;
SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}
P.S. foreach не включает в результат ботов, а второй цикл включает, поэтому нужно добавлять условие на IsPlayerNPC.
И больше 144 ячеек выделять смысла нет, всё равно не отобразится.

Иван Бубнов
13.03.2016, 21:54
Ты ещё кое-что упустил.

Обновил шапку

ziggi
13.03.2016, 21:59
Обновил шапку

Я отредактировал пост, добавив информацию о памяти. Также ты забыл об этом:

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);
(лучше вызывать эти функции один раз)

Иван Бубнов
13.03.2016, 22:10
Я отредактировал пост, добавив информацию о памяти. Также ты забыл об этом:

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);
(лучше вызывать эти функции один раз)

Учусь

- - - Активировано защита от Стяжкина - - -

http://xn--90ai1alafcp.xn--p1ai/upload/iblock/989/2123a1ec4ef180e02ed436a4d276c52d.jpg

Desulaid
13.03.2016, 22:14
А может скреплять строки, а не форматировать?

Иван Бубнов
13.03.2016, 22:19
А может скреплять строки, а не форматировать?

Ты это имел ввиду?

string = params, strcat(string, " ("), strcat(string, string), strcat(string, ")");

PS: Правда на счет string = params не уверен.

Тогда придется еще ник записывать в другой массив

ziggi
13.03.2016, 22:40
Учусь

А что на счёт размера string? Уже третий раз пишу, что выделять больше, чем 144 ячейки смысла нет.

$continue$
13.03.2016, 22:41
MAX_CHATBUBBLE_LENGTH + 1 (нулевой символ туда не входит)

А что на счёт размера string? Уже третий раз пишу, что выделять больше, чем 144 ячейки смысла нет.

DeimoS
13.03.2016, 22:49
Код из шапки не скомпилируется, если подключён foreach :3

Иван Бубнов
13.03.2016, 22:52
Код из шапки не скомпилируется, если подключён foreach :3

Теперь скомпилируется

Desulaid
13.03.2016, 22:55
Во, а что если так?


CMD:do(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");

new
Float:PosX, Float:PosY, Float:PosZ,
world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

strcat(string, params);
strcat(string, " (");
strcat(string, name);
strcat(string, ")");

#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world)
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

Не компилировал, результат не знаю :Р

Иван Бубнов
13.03.2016, 22:58
Во, а что если так?


CMD:do(playerid, params[])
{
#if defined sscanf
if (sscanf(params, "s[124]", params))
#else
if (isnull(params))
#endif
{
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
}

new
Float:PosX, Float:PosY, Float:PosZ,
world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

strcat(string, params);
strcat(string, " (");
strcat(string, name);
strcat(string, ")");

#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

Не компилировал, результат не знаю :Р

Зачем sscanf?

$continue$
13.03.2016, 22:58
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;


Во, а что если так?

Desulaid
13.03.2016, 23:00
Зачем sscanf?

хз, обновил пост

Иван Бубнов
13.03.2016, 23:07
хз, обновил пост

Тогда будет правильнее так, наверное

CMD:do(playerid, params[])
{
#if defined sscanf
if (sscanf(params, "s[124]", params))
#else
if (isnull(params))
#endif
{
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
}

new
Float:PosX, Float:PosY, Float:PosZ,
world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

#if defined sscanf
strcat(string, params[0]);
#else
strcat(string, params);
#endif
strcat(string, " (");
strcat(string, name);
strcat(string, ")");

#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
#if defined sscanf
SetPlayerChatBubble(playerid, params[0], 0xE600FFFF, 30.0, 10000);
#else
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
#endif
return 1;
}

Desulaid
13.03.2016, 23:10
Тогда будет правильнее так, наверное

CMD:do(playerid, params[])
{
#if defined sscanf
if (sscanf(params, "s[124]", params))
#else
if (isnull(params))
#endif
{
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
}

new
Float:PosX, Float:PosY, Float:PosZ,
world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

#if defined sscanf
strcat(string, params[0]);
#else
strcat(string, params);
#endif
strcat(string, " (");
strcat(string, name);
strcat(string, ")");

#if defined foreach
foreach(new i : Player)
{
#else
for(new i = GetPlayerPoolSize(); i != -1; i--)
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
#if defined sscanf
SetPlayerChatBubble(playerid, params[0], 0xE600FFFF, 30.0, 10000);
#else
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
#endif
return 1;
}


Не, только хуже и ты так вроде только первый символ строки покажешь

Иван Бубнов
13.03.2016, 23:11
Не, только хуже и ты так вроде только первый символ строки покажешь

ай лол, тогда sscanf там не уместен.

Иван Бубнов
14.03.2016, 19:52
Обновил

Иван Бубнов
19.03.2016, 16:00
Обновил

L0ndl3m
19.03.2016, 17:40
Можете реализовать команду без использования функции strcat?

Иван Бубнов
19.03.2016, 17:47
Можете реализовать команду без использования функции strcat?


CMD:do(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX, Float:PosY, Float:PosZ, world, interior,
string[MAX_CHATBUBBLE_LENGTH+1];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, string, sizeof(string));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

format(string, sizeof(string), "%s (%s)", params, string);

#if defined foreach
foreach(new i : Player)
{
#else
for(new i = -1; ++i != GetPlayerPoolSize();)
{
if ((0 == IsPlayerConnected(i))
|| (0 != IsPlayerNPC(i))) continue;
#endif
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

VVWVV
19.03.2016, 18:00
1. Используй упакованные строки, ибо strcat позволяет это сделать.

string[MAX_CHATBUBBLE_LENGTH+1 char];

strcat(string, params);
strcat(string, !" (");
strcat(string, name);
strcat(string, !")");
2. Использовать функцию GetPlayerPoolSize при каждой итерации - плохо.

for(new i = -1; ++i != GetPlayerPoolSize();)
3. Не стоит забывать о тех, кто ещё сидит на версии 0.3e.

#if defined foreach
foreach (new i: Player)
#else
#if defined GetPlayerPoolSize
for (new i = GetPlayerPoolSize(); --i != -1;)
#else
for (new i = -1; ++i != MAX_PLAYERS;)
#endif
if (IsPlayerConnected(i) == 0 || IsPlayerNPC(i) != 0) continue;
else
#endif
{}

UPD:


CMD:do(playerid, params[])
{
if (isnull(params))
return SendClientMessage(playerid, -1, !"Введите: /do <текст>");
new
Float:PosX, Float:PosY, Float:PosZ, world, interior,
name[MAX_PLAYER_NAME], string[MAX_CHATBUBBLE_LENGTH+1 char];

GetPlayerPos(playerid, PosX, PosY, PosZ);
GetPlayerName(playerid, name, sizeof(name));

world = GetPlayerVirtualWorld(playerid);
interior = GetPlayerInterior(playerid);

strcat(string, params);
strcat(string, !" (");
strcat(string, name);
strcat(string, !")");

#if defined foreach
foreach(new i: Player)
#else
#if defined GetPlayerPoolSize
for(new i = GetPlayerPoolSize() + 1; --i != -1;)
#else
for(new i = -1; ++i != MAX_PLAYERS;)
#endif
if ((0 == IsPlayerConnected(i)) || (0 != IsPlayerNPC(i))) continue;
else
#endif
{
if(0 == IsPlayerInRangeOfPoint(i, 15.0, PosX, PosY, PosZ)) continue;
if((GetPlayerVirtualWorld(i) != world )
|| (GetPlayerInterior(i) != interior)) continue;

SendClientMessage(i, 0xE600FFFF, string);
}
SetPlayerChatBubble(playerid, params, 0xE600FFFF, 30.0, 10000);
return 1;
}

NewGreen
19.03.2016, 18:49
3. Не стоит забывать о тех, кто ещё сидит на версии 0.3e.

#if defined foreach
foreach (new i: Player)
#else
#if defined GetPlayerPoolSize
for (new i = GetPlayerPoolSize(); --i != -1;)
#else
for (new i = -1; ++i != MAX_PLAYERS;)
#endif
if (IsPlayerConnected(i) == 0 || IsPlayerNPC(i) != 0) continue;
else
#endif
{}

Использовать for в такой извращенной форме плохо, когда есть уже готовые решения:


for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++)

а сейчас что мы имеем:

GetPlayerPoolSize() - согласно wiki (https://wiki.sa-mp.com/wiki/GetPlayerPoolSize) -Gets the highest playerid currently in use on the server. - т.е. получает самый старший playerid который используется в настоящее время на сервере.

Допустим старший ID у нас 10:

Запускаем код:


for (new i = 10/*GetPlayerPoolSize()*/; --i != -1;)
printf("i = %d", i);


Получаем:



i = 9
i = 8
i = 7
i = 6
i = 5
i = 4
i = 3
i = 2
i = 1
i = 0


т.е. ID номер 10 исключается из цикла.

Иван Бубнов
19.03.2016, 18:51
Обновлено

- - - Добавлено - - -


Использовать for в такой извращенной форме плохо, когда есть уже готовые решения:


for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++)


Обоснуй

NewGreen
19.03.2016, 18:53
Обновлено

- - - Добавлено - - -



Обоснуй

см. спойлер в моем сообщении выше

Иван Бубнов
19.03.2016, 18:56
Стыд и позор. /dell

VVWVV
19.03.2016, 18:56
см. спойлер в моем сообщении выше

Сам заметил, при тестировании. Спасибо. Код обновил (добавил свою версию).

for(new i = GetPlayerPoolSize() + 1; --i != -1;)


for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++)
Зачем ещё одна переменная?


Стыд и позор. /dell

Извиняюсь, но я был не прав.

Иван Бубнов
19.03.2016, 19:02
Сам заметил, при тестировании. Спасибо. Код обновил (добавил свою версию).



Извиняюсь, но я был не прав.

Не тебе это) Я просто кое что лишнее написал грину :hi:

NewGreen
19.03.2016, 19:25
Не тебе это) Я просто кое что лишнее написал грину :hi:

Ну раз это было мне, то обоснуйте, как вы выразились ранее

- - - Добавлено - - -



Зачем ещё одна переменная?


Так отсчет ID начинается с нуля, хоть это может быть и не столь важно

VVWVV
19.03.2016, 19:37
Ну раз это было мне, то обоснуйте, как вы выразились ранее

- - - Добавлено - - -



Так отсчет ID начинается с нуля, хоть это может быть и не столь важно

Зачем нам тратить память под ненужную переменную?

NewGreen
19.03.2016, 20:13
Зачем нам тратить память под ненужную переменную?

Для вас принципиально важно ?, я написал это, так как, это одна классических конструкций цикла for, в том же wiki она используется.

VVWVV
19.03.2016, 20:21
Для вас принципиально важно ?, я написал это, так как, это одна классических конструкций цикла for, в том же wiki она используется.

Для вас, может быть, нет, а для меня - да.
Впрочем, это ещё и оптимизация скрипта.

Иван Бубнов
19.03.2016, 20:28
Закрыто.