PDA

Просмотр полной версии : [Вопрос] [CMD] Использование ID и имени игрока в командах.



Alexey_Nikiforov
24.02.2016, 19:05
Как сделать что бы можно было использовать для выполнения команды как ID игрока так и его имя.
В данном случае указано ID и имя.
Но работает не так как нужно.


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

Суть проблемы заключается в том что если написать вот так.
/sethp A 0

Эта команда убъет всех игроков у кого имя начинается на A
Как сделать что бы считывало ники игроков на сервере.
И если не найдет совпадения писало что игрок не в сети.

BadPawn
24.02.2016, 19:18
U - ид и имя игрока. Все верно.

Если нет эффекта, то попробуй не через созданную переменную, а по стандарту params[0].

Так же, вместо создания переменных для хранения ида игрока, лвл, уровень и т.д. в командах, советую просто дефайнить. Проще ведь)

После if.sscanf.params."ud".params0.params1 п шем следующее:

#define id params[0]
В конце команды до return 1:

#undef id

Alexey_Nikiforov
24.02.2016, 19:41
Подредактировал вопрос.

DeimoS
24.02.2016, 20:11
U - ид и имя игрока. Все верно.

Если нет эффекта, то попробуй не через созданную переменную, а по стандарту params[0].

Так же, вместо создания переменных для хранения ида игрока, лвл, уровень и т.д. в командах, советую просто дефайнить. Проще ведь)

После if.sscanf.params."ud".params0.params1 п шем следующее:

#define id params[0]
В конце команды до return 1:

#undef id

Просвещение здесь (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)

Alexey_Nikiforov
24.02.2016, 20:16
Просвещение здесь (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)
До туда мало кто доходит =)

_lizard
24.02.2016, 20:44
На будущее, здоровье хранится в переменных типа Float

vovandolg
24.02.2016, 21:11
На будущее, здоровье хранится в переменных типа Float

Ну так он чтобы не писать в команде 100.0 пишет 100 и округляет во Float уже в SetPlayerHealth..

_lizard
24.02.2016, 21:12
Ну так он чтобы не писать в команде 100.0 пишет 100 и округляет во Float уже в SetPlayerHealth..

DC писал статью по этому поводу уже и объяснял, почему это плохо

DeimoS
24.02.2016, 21:33
DC писал статью по этому поводу уже и объяснял, почему это плохо

Если ты не заметил, он там сам указал конвертацию значения переменной в float. Сделано это намеренно и ничего страшного в данном случае нет. А Кортез имел ввиду подобные ошибки в глобальном масштабе.



Как это сделать в sscanf я, увы, не знаю, но вот как бы я это реализовал собственными силами:


stock FindPlayerInServer(buffer[], bool:ignorecase = false)//true - регистр не учитывается | false - учитывается
{
if((buffer[0] >= 48 && buffer[0] <= 57 && ((buffer[1] >= 48 && buffer[1] <= 57) || buffer[1] == EOS) &&
((buffer[2] >= 48 && buffer[2] <= 57) || buffer[2] == EOS)) && buffer[3] == EOS) return strval(buffer);
else
{
if(strlen(buffer) > MAX_PLAYER_NAME) return INVALID_PLAYER_ID;
new ds_player_name[MAX_PLAYER_NAME+1];

for(new i = GetPlayerPoolSize(); i != -1; i--)
//for(new i = GetMaxPlayers()-1; i != -1; i--)
//for(new i; i < MAX_PLAYERS; i++)
//foreach(new i: Player)
{
if(!IsPlayerConnected(i)) continue;//Если включишь foreach, удали эту строку
GetPlayerName(i, ds_player_name, MAX_PLAYER_NAME);
if(!strcmp(ds_player_name, buffer, ignorecase)) return i;
}
return INVALID_PLAYER_ID;
}
}


stock FindPlayerInServer(buffer[], bool:ignorecase = false)
Собственно, два параметра. В один строка, в которой находится ник или ID, а во втором указывается то, стоит ли учитывать регистр при поиске ника или нет (если не указывать, регистр будет учитываться)


if((buffer[0] >= 48 && buffer[0] <= 57 && ((buffer[1] >= 48 && buffer[1] <= 57) || buffer[1] == EOS) &&
((buffer[2] >= 48 && buffer[2] <= 57) || buffer[2] == EOS)) && buffer[3] == EOS) return strval(buffer);
Собственно логика сей "страшной" проверки такова: в SA-MP максимальный ID игрока - 999 (1000 игроков. Первый ID - 0 => последний - 999), следовательно, если в первой ячейке записана цифра, во второй и третьей так же цифра или нуль-символ, а в четвёртой - нуль символ, значит в массиве указан именно ID и его смело можно возвращать.

Иначе


if(strlen(buffer) > MAX_PLAYER_NAME) return INVALID_PLAYER_ID;
если в функцию передана строка больше MAX_PLAYER_NAME, значит указан явно не ник и смело можно возвращать невалидный ID (то бишь, что игрок не найден)


for(new i = GetPlayerPoolSize(); i != -1; i--)
Собстно, запускаем цикл на всех игроков, в котором извлекаем ник каждого игрока и записываем с существующим (GetPlayerPoolSize - функция, добавленная в 0.3.7, которая вернёт ID последнего игрока). Так же там указаны другие вариации циклов, если этот тебя не устроит




CMD:sethp(playerid,params[]){
new str[50], playa[MAX_PLAYER_NAME+1], health;
if(sscanf(params,"s[24]i", playa, health)) return SCM(playerid, COLOR_WHITE,"Используйте: /sethp [id/имя][кол-во жизней]");
playa[0] = FindPlayerInServer(playa, false);//У меня ник DeimoS. При вводе "Deimos" скажет, что игрок не найден
//playa[0] = FindPlayerInServer(playa, true);//У меня ник DeimoS. При вводе "Deimos" скажет, что игрок найден
if(!IsPlayerConnected(playa[0])) return SCM(playerid, COLOR_WHITE, "Игрок не в сети");
if(health < 0 || health > 100) return SCM(playerid, COLOR_GREY, "Нельзя дать менее 0 и более 100 жизней.");
format(str,sizeof(str), "%s установил вам жизней %d",pInfo[playerid][pName],health);
SetPlayerHealth(playa[0],float(health));
SCM(playa[0],COLOR_WHITE, str);
return 1;
}

stock FindPlayerInServer(buffer[], bool:ignorecase = false)//true - регистр не учитывается | false - учитывается
{
if((buffer[0] >= 48 && buffer[0] <= 57 && ((buffer[1] >= 48 && buffer[1] <= 57) || buffer[1] == EOS) &&
((buffer[2] >= 48 && buffer[2] <= 57) || buffer[2] == EOS)) && buffer[3] == EOS) return strval(buffer);
else
{
if(strlen(buffer) > MAX_PLAYER_NAME) return INVALID_PLAYER_ID;

for(new i = GetPlayerPoolSize(); i != -1; i--)
//for(new i = GetMaxPlayers()-1; i != -1; i--)
//for(new i; i < MAX_PLAYERS; i++)
//foreach(new i: Player)
{
if(!IsPlayerConnected(i)) continue;//Если включишь foreach, удали эту строку
if(!strcmp(pInfo[i][pName], buffer, ignorecase)) return i;
}
return INVALID_PLAYER_ID;
}
}

Функция вернёт INVALID_PLAYER_ID, если игрок с таким ID/ником не найден

ziggi
24.02.2016, 23:23
Эта команда убъет всех игроков у кого имя начинается на A

Не правда, эта команда убьёт лишь одного игрока, имя которого начинается на A. Лично я не вижу в этом проблемы.

Alexey_Nikiforov
25.02.2016, 01:25
Не правда, эта команда убьёт лишь одного игрока, имя которого начинается на A. Лично я не вижу в этом проблемы.
Мне надо что бы она убила человека при 100% совпадении имени.