PDA

Просмотр полной версии : [Вопрос] Выбор нужного игрока из диалога



2ol
28.08.2015, 05:52
Ломаю голову уже несколько дней.
Что я хочу увидеть от кода? При вызове диалога идет отбор по игрокам, которые находятся в трех метрах от playerid (по коду все ясно), но мне надо передать предмет именно тому игроку, на которого я нажал (из диалога).


Возле меня стоят три игрока, допустим, их зовут PlayerOne[1], PlayerTwo[2] и PlayerThree[3], мне надо передать что-то игроку с ником PlayerTwo и ID:2.
Диалог, естественно, будет таким:


ShowPlayerDialog(playerid, 8, DIALOG_STYLE_LIST, "Инвентарь > Передать", "PlayerOne[1]\nPlayerTwo[2]\nPlayerThree[3]", "Выбор", "Назад");

Но ведь вместо этих ников и ID могут быть и другие. Как мне передать игроку с ID:2 предмет?




case 2: {
if(!response) return ShowPlayerDialog(playerid, 6, DIALOG_STYLE_TABLIST, "Инвентарь", string, "Выбор", "Выйти");
new Float:player_pos[3],
string_foreach[31],
strcat_string[24*6];
GetPlayerPos(playerid, player_pos[0], player_pos[1], player_pos[2]);
foreach(Player, i)
{
if(!IsPlayerInRangeOfPoint(i, 3.0, player_pos[0], player_pos[1], player_pos[2])) continue;
format(string_foreach, sizeof(string_foreach), "%s[%d]\n", PlayerInfo[i][pName], i);
strcat(strcat_string, string_foreach);
}
return ShowPlayerDialog(playerid, 8, DIALOG_STYLE_LIST, "Инвентарь > Передать", strcat_string, "Выбор", "Назад");
}


p.s. на массивы не смотрите, потом все пересчитаю и сделаю как надо.

$continue$
28.08.2015, 16:08
if(!IsPlayerInRangeOfPoint(...))
i - хранит ID игроков в радиусе 3.0, в чем проблема?

Daniel_Cortez
28.08.2015, 19:55
if(!IsPlayerInRangeOfPoint(...))
i - хранит ID игроков в радиусе 3.0, в чем проблема?

Т.е. при нажатии кнопки перебирать игроков ещё раз и составлять список? Не пойдёт, за пару секунд между показом диалогов и нажатием кнопки кто-то из игроков может отойти или радом встанет кто-нибудь ещё и на N-ом месте в списке вместо Пети будет Вася. Я уже не говорю о том, насколько это затратно будет перебирать игроков и составлять заново список.

По сабжу: самым простым выходом будет использовать GetPlayerTargetPlayer: просто нацеливаетесь на игрока, нажимаете Y и перед вам открывается диалог передачи предметов этому игроку.

Второй способ:


// макс. кол-во игроков в диалоге передачи
const MAX_GIVE_DLG_TARGET_PLAYERS = 8;
new give_dlg_target_players[MAX_PLAYERS][MAX_GIVE_DLG_TARGET_PLAYERS];

Перед показом диалога записываете ID всех стоящих рядом игроков в массив и после нажатия кнопки просто берёте соответствующий ID из массива.

Третий способ:


const MAX_GIVE_DLG_TARGET_PLAYERS = 8;
// кол-во символов в строке диалога: длина ника минус символ конца строки ("\0")
// плюс знак переноса ("\n") или конца строки, если последняя строка в диалоге.
const NICK_NAME_STR_LEN = MAX_PLAYER_NAME-1+1;
// рационально рассчитываем размер строковой переменной
new buffer[NICK_NAME_STR_LEN * MAX_GIVE_DLG_TARGET_PLAYERS];
// ...
return ShowPlayerDialog(playerid, 8, DIALOG_STYLE_LIST, "Инвентарь > Передать", /* ... */);

Это нигде не задокументировано, но если показать игроку диалог со стилем DIALOG_STYLE_LIST, то в коллбэке OnDialogResponse будет не только ID выбранной строки (listitem), но и содержимое той строки (inputtext). В итоге в inputtext будет никнейм выбранного игрока - вам останется лишь перебрать всех подключенных игроков, пока не найдёте нужного игрока. Есть вероятность, что выбранный игрок за пару секунд успеет сменить ник, но это маловероятно. Тот же самый эффект будет, если выбранный игрок выйдет с сервера - нужно всего лишь учесть такой вариант и показать сообщение об ошибке, если не нашли игрока с выбранным ником.
И да, лучше заранее кешировать никнеймы игроков (при подключении сохранять их в массив), чтобы не вызывать по over9000 раз функцию GetPlayerName. Примерно завтра или послезавтра я постараюсь выложить инклуд как раз для таких целей. Следите за обновлениями на сайте.

#Vito
28.08.2015, 22:07
Можно еще сделать как то так:

new Player[MAX_PLAYERS][15];

CMD: peredat() // КМД показа диалога
{
new Float:Pos[3], a;
GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
for(new i; i < MAX_PLAYERS; i++)
{
if(!IsPlayerInRangeOfPoint(i, 3.0, Pos[0], Pos[1], Pos[2]) continue;
Player[playerid][a] = i;
a++;
// Тут узнаешь ники и т.д. и т.п.
ShowPlayerDialog(playerid, 8, DIALOG_STYLE_LIST, "Инвентарь > Передать", "PlayerOne[1]\nPlayerTwo[2]\nPlayerThree[3]", "Выбор", "Назад");
}
return 1;
}

И использовать
Player[playerid][listitem]

Ну, должно работать

$continue$
28.08.2015, 22:38
Можно еще сделать как то так:

new Player[MAX_PLAYERS][15];

CMD: peredat() // КМД показа диалога
{
new Float:Pos[3], a;
GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
for(new i; i < MAX_PLAYERS; i++)
{
if(!IsPlayerInRangeOfPoint(i, 3.0, Pos[0], Pos[1], Pos[2]) continue;
Player[playerid][a] = i;
a++;
// Тут узнаешь ники и т.д. и т.п.
ShowPlayerDialog(playerid, 8, DIALOG_STYLE_LIST, "Инвентарь > Передать", "PlayerOne[1]\nPlayerTwo[2]\nPlayerThree[3]", "Выбор", "Назад");
}
return 1;
}

И использовать
Player[playerid][listitem]

Ну, должно работать

И словить выход за пределы массива...

#Vito
28.08.2015, 22:51
И словить выход за пределы массива...
Ничего не мешает его увеличить..

new Player[MAX_PLAYERS][MAX_PLAYERS];

$continue$
28.08.2015, 23:35
R
Ничего не мешает его увеличить..

new Player[MAX_PLAYERS][MAX_PLAYERS];

Изврат


#undef MAX_PLAYERS
const MAX_PLAYERS = 20;

Daniel_Cortez
28.08.2015, 23:51
Ничего не мешает его увеличить..

new Player[MAX_PLAYERS][MAX_PLAYERS];


R

Изврат


#undef MAX_PLAYERS
const MAX_PLAYERS = 20;


...



const MAX_GIVE_DLG_TARGET_PLAYERS = 8;