PDA

Просмотр полной версии : [Вопрос] Метки на радаре



PawnoNoob
10.07.2016, 23:09
Всем привет. Я уверен в том, что этот вопрос задавался несколько десятков (а может и сотен) раз, да и ответ на этот вопрос давался столько же, но, к сожалению, конкретно этого вопроса я не нашёл на просторах этого форума (да и в поисковой системе тоже что-то не удалось найти). Так вот, всё опишу ниже.

Что я делал до того, как задать этот вопрос:

ShowPlayerMarkers(PLAYER_MARKERS_MODE_STREAMED);
После всего этого метка начала действительно пропадать, но уже ближе к концу самой пирамиды (чистый new.pwn), а это довольно-таки многовато для меня. Как уменьшить это расстояние?

И я так и не понял, за что отвечает функция LimitPlayerMarkerRadius? В Wiki написано, что устанавливает радиус этой метки, а на стороннем портале пишут следующее: "Функция определяет, на каком расстоянии будет виден маркер.".

DeimoS
10.07.2016, 23:22
И я так и не понял, за что отвечает функция LimitPlayerMarkerRadius? В Wiki написано, что устанавливает радиус этой метки, а на стороннем портале пишут следующее: "Функция определяет, на каком расстоянии будет виден маркер.".

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

PawnoNoob
10.07.2016, 23:23
Самым лучшим способом будет просто взять и проверить, не?
Не уверен, что кто-то из форумчан часто работал с этой функцией и даст тебе точный ответ

Вот именно, что проверял, да и не раз, результата вообще никакого не заметил, ставил и 10.0, и 20.0. Эффекта по-моему вообще никакого нет.

Geebrox
10.07.2016, 23:31
LimitPlayerMarkerRadius - устанавливает радиус (расстояние игрока от другого игрока, при котором появится метка на карте) показа метки


В Wiki написано, что устанавливает радиус этой метки

и


"Функция определяет, на каком расстоянии будет виден маркер."

имеется ввиду одно и то же

PawnoNoob
10.07.2016, 23:34
LimitPlayerMarkerRadius - устанавливает радиус (расстояние игрока от другого игрока, при котором появится метка на карте) показа метки



и



имеется ввиду одно и то же
Хм, эти две функции нужно использовать вместе? Типа:


ShowPlayerMarkers(PLAYER_MARKERS_MODE_STREAMED);
LimitPlayerMarkerRadius(например, 50.0);
Или как-то по-другому?

DeimoS
10.07.2016, 23:39
Вот именно, что проверял, да и не раз, результата вообще никакого не заметил, ставил и 10.0, и 20.0. Эффекта по-моему вообще никакого нет.

Сам я с этой функцией работал, примерно, году в 13-ом последний раз и, как мне помнится, тоже не добился желаемого успеха.

Если ничего не получится, можешь попробовать сделать свой костыль в виде прикрепления к каждому игроку динамической зоны и использовании вот такой функции:

stock TogglePlayerOnMapForPlayer(playerid, showplayerid, bool:visible) SetPlayerMarkerForPlayer(playerid, showplayerid, (GetPlayerColor(showplayerid) | 0xFF) - (visible ? 0x00 : 0xFF));
//Функцию набросал прямо тут и не уверен, что угадал с правильностью playerid и showplayerid

То бишь, игрок один игрок зашёл в зону другого и для того, кто зашёл:

TogglePlayerOnMapForPlayer(playerid, giveplayerid, true);// playerid - кто зашёл в зону, giveplayerid - к кому зашли в зону
// Покажет иконку showplayerid для playerid
И когда вышел

TogglePlayerOnMapForPlayer(playerid, giveplayerid, false);
Так сможешь чуть ли не прямо в игре регулировать расстояние прорисовки иконок.

Позже, мб, инк напишу с этой системой, если никто не опередит и если SetPlayerMarkerForPlayer вообще работает

ziggi
11.07.2016, 00:58
Стоит немного поискать и можно найти подобные сообщения где-то ещё (http://forum.sa-mp.com/showthread.php?t=563915)

ziggi
11.07.2016, 02:49
Я изучил работу этих маркеров и выяснил, что значение PLAYER_MARKERS_MODE_STREAM отвечает за отображение маркеров игроков в стриме (как очевидно из названия), а маркеры в зоне стрима отрисовываются на стороне клиента.

Значение PLAYER_MARKERS_MODE_GLOBAL запускает функцию постоянного обновления маркеров раз в 2.5 секунды. Именно в эту функцию идёт значение, переданное с помощью LimitPlayerMarkerRadius (значение, кстати, идёт в квадрате, видимо изначально Kye хотел обойтись без sqrt в вычислении расстояния, но потом забыл убрать возведение в квадрат).

То есть за отрисовку маркеров игроков в стриме отвечает клиент, а в глобале - сервер, именно поэтому при покидании зоны стрима иконка на карте появляется не сразу.

Из-за того, что клиент автоматически удаляет глобальный маркер при входе в стрим, исправить работу стандартных маркеров не представляется возможным. Хотя что стоит добавить вызов функции обновления маркеров при входе/выходе игрока в/из стрима, что исправит задержку между появлениями маркеров, и что стоит добавить передачу расстояния из LimitPlayerMarkerRadius в клиент и поставить одну небольшую проверку на расстояние? Эх...

Кстати, функция SetPlayerMarkerForPlayer - всего лишь SetPlayerColorForPlayer, то есть эта функция изменяет цвет одного игрока для другого.

Отвечаю на вопрос автора:

И я так и не понял, за что отвечает функция LimitPlayerMarkerRadius?
Функция LimitPlayerMarkerRadius отвечает за расстояние (точнее за квадрат расстояния) на котором будет отрисовываться маркеры игроков, которые находятся вне стрима. Эту функцию имеет смысл использовать только в режиме PLAYER_MARKERS_MODE_GLOBAL.

DeimoS
11.07.2016, 09:44
Кстати, функция SetPlayerMarkerForPlayer - всего лишь SetPlayerColorForPlayer, то есть эта функция изменяет цвет одного игрока для другого.


Так я и хотел работать с иконками путём изменения цвета одного игрока для другого. Точнее, изменения насыщенности, которая отвечает за прозрачность иконки на радаре.

ziggi
11.07.2016, 10:57
Так я и хотел работать с иконками путём изменения цвета одного игрока для другого. Точнее, изменения насыщенности, которая отвечает за прозрачность иконки на радаре.

Дак я ничего и не говорю, это единственный вариант.

PawnoNoob
11.07.2016, 20:49
Теперь знаю больше, спасибо огромное за помощь :thank_you:

DeimoS
12.07.2016, 09:56
Я тут вчера набросал реализацию своей идеи (начал делать заготовку для инклюда) и вот что вышло (может кому пригодится)

#if !defined DEFAULT_PLAYER_MARKER_RADIUS
#define DEFAULT_PLAYER_MARKER_RADIUS 300.0
#endif
enum e_PLAYER_MARKER_INFO
{
mark_id,
Float:mark_radius,
transparent
}
new pl_mark[MAX_PLAYERS][e_PLAYER_MARKER_INFO];


stock TogglePlayerOnMapForPlayer(playerid, showplayerid, bool:visible)
{
new map_color = GetPlayerColor(showplayerid);
if((map_color & 0xFF) != 0x00) pl_mark[playerid][transparent] = map_color & 0xFF;
SetPlayerMarkerForPlayer(playerid, showplayerid, (map_color | 0xFF) - (visible ? 0x00 : pl_mark[playerid][transparent]));
return 1;
}

stock UpdateRadiusForPlayerMarker(playerid, Float:radius)
{
if(pl_mark[playerid][mark_id] == -1) return 0;
pl_mark[playerid][mark_radius] = radius;
DestroyDynamicArea(pl_mark[playerid][mark_id]);
printf("\n%d", pl_mark[playerid][mark_id] = CreateDynamicSphere(0.0, 0.0, 0.0, pl_mark[playerid][mark_radius], -1, -1, -1));
printf("%d\n", AttachDynamicAreaToPlayer(pl_mark[playerid][mark_id], playerid));
return 1;
}

cmd:radius(playerid, params[])
{
if(isnull(params) || !(params[0] >= '0' && params[0] <= '9')) return SendClientMessage(playerid, -1, "Введите радиус");
new Float: radius = float(strval(params));
new string[30];
foreach(new i: Player)
{
format(string, sizeof(string), "%d", UpdateRadiusForPlayerMarker(playerid, radius));
SendClientMessage(playerid, -1, string);
}
return 1;
}


public OnGameModeInit()
{
ShowPlayerMarkers(PLAYER_MARKERS_MODE_GLOBAL);
LimitPlayerMarkerRadius(10000.0);
for(new i; i < sizeof(pl_mark); i++)
{
pl_mark[i][mark_id] = -1;
pl_mark[i][transparent] = 0xFF;
pl_mark[i][mark_radius] = DEFAULT_PLAYER_MARKER_RADIUS;
}
return 1;
}

public OnPlayerSpawn(playerid)
{
if(pl_mark[playerid][mark_id] == -1)
{
pl_mark[playerid][mark_id] = CreateDynamicSphere(0.0, 0.0, 0.0, pl_mark[playerid][mark_radius], -1, -1, -1);
AttachDynamicAreaToPlayer(pl_mark[playerid][mark_id], playerid);
}

SetPlayerPos(playerid, 1830.3783, 1340.1572, 14.3746);
return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
if(pl_mark[playerid][mark_id] != -1)
{
DestroyDynamicArea(pl_mark[playerid][mark_id]);
pl_mark[playerid][mark_id] = -1;
}
pl_mark[playerid][transparent] = 0xFF;
return 1;
}


public OnPlayerEnterDynamicArea(playerid, areaid)
{
new string[30];
foreach(new i: Player)
{
if(i == playerid) continue;
if(areaid != pl_mark[i][mark_id]) continue;
TogglePlayerOnMapForPlayer(i, playerid, true);
format(string, sizeof(string), "%d показан для %d", playerid, i);
SendClientMessageToAll(-1, string);

}
return 1;
}
public OnPlayerLeaveDynamicArea(playerid, areaid)
{
new string[30];
foreach(new i: Player)
{
if(i == playerid) continue;
if(areaid != pl_mark[i][mark_id]) continue;
TogglePlayerOnMapForPlayer(i, playerid, false);
format(string, sizeof(string), "%d скрыт для %d", playerid, i);
SendClientMessageToAll(-1, string);
}
return 1;
}

Код чисто написан для теста (некоторая "ненужная" информация выдаётся в чат и прочее) и я сразу пытался адаптировать его под расширенные возможности (обновлять радиус отображения маркеров для всех/определённого игрока прямо в игре и т.п.). В общем, чисто на посмотреть.

P.S. Тестировал всё на одном компьютере с использованием песочницы и заметил, что то ли функция AttachDynamicAreaToPlayer отказывается крепить зону к игроку, который АФК, то ли OnPlayerEnterDynamicArea/OnPlayerLeaveDynamicArea как-то отказывается срабатывать нормально, но смысл в том, что если попробовать обновить радиус зон (пока реализовано обновление для всех сразу) и кто-то будет стоять АФК, система начнёт глючить (у АФК-шника радиус зоны останется старым).
Вполне возможно, что это косяк моего кода. Вчера просто не было времени проверить. Просто если кто-то решит копаться в моём говнокоде, имейте это ввиду.
И да, я, похоже, стандартные маркеры настроил немного неверно. В общем, работать ещё есть над чем :3


UPD: Бага с AFK никакого нет. Всему виной мои кривые руки и невнимательность. Скоро запилю инклюд

ziggi
12.07.2016, 14:06
LimitPlayerMarkerRadius лучше убрать, чтобы внутренний стриммер не рассчитывал дистанцию.