PDA

Просмотр полной версии : [Урок] Работаем с "чекпоинтами".



wAx
21.07.2014, 00:59
Здравствуйте!

В этом уроке, я хочу поведать о чекпоинтах, с чем их едят и как их подавать. В общем, на основе нашего урока, мы попытаемся сделать простенькую работу. И так, начнем.


Что такое чекпоинт и как его создавать.

Что-же такое чекпоинт? Объясню на пальцах, чекпоинт - это такая красная метка, которая отражается на миникарте вне зависимости от дистанции между игроком и меткой. Еще одной важной деталью, будет то, что для игрока можно установить всего 1 видимый чекпоинт. И так, чекпоинты делятся на 2 типа, это: обычные, чекпоинты для игрока, и чекпоинты указатели. Выглядят эти чекпоинты примерно следующим образом:
http://ihost.pro-pawn.ru/image.php?dm=8ZZM (http://ihost.pro-pawn.ru/?pm=8ZZM)
Чекпоинт обычной метки для игрока.
http://ihost.pro-pawn.ru/image.php?dm=I35J (http://ihost.pro-pawn.ru/?pm=I35J)
Чекпоинт-указатель.

И все-же, как нам создавать подобные чекпоинты?

Ну.. Для этого в SA:MP существует пара функций, сейчас я расскажу о них.



SetPlayerCheckpoint(playerid, Float:x, Float:y, Float:z, Float:size);
Данная функция используется для создания обычной метки для игрока, в ней используются следующие параметры:


playerid ID Игрока
Float:x x-координата для чекпоинта
Float:y y-координата для чекпоинта
Float:z z-координата для чекпоинта
Float:size Размер чекпоинта


SetPlayerRaceCheckpoint(playerid, type, Float:x, Float:y, Float:z, Float:nextx, Float:nexty, Float:nextz, Float:size)
Данная функция используется для создания метки-указателя для игрока, в ней используются следующие параметры:


playerid ID игрока
type Тип метки.0-Обычная, 1-Финиш, 2-Ничего(Просто метка), 3-Метка-кольцо обычная, 4-Метка-кольцо финиш
Float:x X-Координата
Float:y Y-Координата
Float:z Z-Координата
Float:nextx X-Координата следующей метки, для определения направления указателя(стрелки)
Float:nexty Y-Координата следующей метки, для определения направления указателя(стрелки)
Float:nextz Z-Координата следующей метки, для определения направления указателя(стрелки)
Float:size Размер(диаметр) метки


Также, для работы с "метками" предусмотрено пару других функций (в том числе и автовызываемых).


DisablePlayerCheckpoint(playerid);
Функция скрывает обычную метку, созданную для игрока. Возвратит false, если игрок не подключен к серверу.

DisablePlayerRaceCheckpoint(playerid);
Функция аналогичная предыдущей, только создана для скрытия метки-указателя.

IsPlayerInCheckpoint(playerid);
Функция проверяет нахождение игрока в чекпоинте.

IsPlayerInRaceCheckpoint(playerid);
Функция проверяет нахождение игрока в метке-указателе.

Перейдем к автовызываемым функциям.


OnPlayerEnterCheckpoint(playerid);
Функция вызывается, когда игрок оказывается внутри созданной метки.

OnPlayerLeaveCheckpoint(playerid);
Функция вызывается, когда игрок покидает созданную метку.

OnPlayerEnterRaceCheckpoint(playerid);
Функция вызывается, когда игрок оказывается внутри созданной метки-указателе.

OnPlayerLeaveRaceCheckpoint(playerid);
Функция вызывается, когда игрок покидает созданную метку-указатель.

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

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


Использование чекпоинтов "На деле".

На основе полученных знаний и изученных функций, попробуем с вами написать пару простеньких скриптов, дабы полностью понять что-же такое эти чекпоинты. Для начала давайте поставим для себя задачу, к примеру:
- Сделать чекпоинт для игрока, встав на который он получит в руки коробку, затем ему будет указана метка куда нужно отнести эту коробку.
- Сделать метку-указатель по команде для игрока, достигнув которую игроку выведет сообщение о достижении метки.

И так, задачи поставлены, теперь перейдем к исполнению, естественно по-порядку.


Давайте для начала работы игрока, создадим команду /startwork.


if(!strcmp(cmdtext, "/startwork"))
{
if(!GetPVarInt(playerid,"_work"))
{
DeletePVar(playerid, "_in_hand");
SetPVarInt(playerid, "_work", 1);
SendClientMessage(playerid, -1, "Работа была начата.");
DisablePlayerCheckpoint(playerid); // См.примечание 1 в конце темы.
SetPlayerCheckpoint(playerid, 603.3618,820.8993,-43.0697, 2.0);
}
else
{
DeletePVar(playerid, "_work");
DisablePlayerCheckpoint(playerid);
SendClientMessage(playerid, -1, "Работа была закончена.");
}
}

Теперь, давайте проверим игрока на нахождение в нужной нам метке. Сделаем это в паблике OnPlayerEnterCheckpoint. Ну и собственно с помощью этого паблика мы будем управлять игроком, забирать коробку и устанавливать чекпоинт подбора, или же отдавать коробку и устанавливать метку склада.


public OnPlayerEnterCheckpoint(playerid)
{
if(GetPVarInt(playerid, "_work"))
{
if(!GetPVarInt(playerid, "_in_hand"))
{
if(!IsPlayerInRangeOfPoint(playerid, 3.0, 603.3618,820.8993,-43.0697)) return 1; // См. примечание 2 в конце темы.
SetPlayerAttachedObject(playerid,0,1271,1,0.172000,0.424999,-0.007999,2.999999,5.899999,-5.399998,0.415999,0.402000,1.000000);
DisablePlayerCheckpoint(playerid);
ApplyAnimation(playerid, "CARRY", "liftup", 4.1, 0, 0, 0, 0, 0, 1);
SetPlayerCheckpoint(playerid, 602.1813,867.8220,-42.9609, 2.0);
SetPlayerSpecialAction(playerid, 25);
SetPVarInt(playerid, "_in_hand", 1);
}
else
{
if(!IsPlayerInRangeOfPoint(playerid, 3.0, 602.1813,867.8220,-42.9609)) return 1;
RemovePlayerAttachedObject(playerid, 0);
SetPlayerSpecialAction(playerid, 0);
ApplyAnimation(playerid, "CARRY", "putdwn", 4.1, 0, 0, 0, 0, 0, 1);
DisablePlayerCheckpoint(playerid);
SetPlayerCheckpoint(playerid, 603.3618,820.8993,-43.0697);
DeletePVar(playerid, "_in_hand");
}
}
return 1;
}


Первая цель достигнута, отправляемся за второй.

Для установки метки, мы будем использовать с вами команду /grotti, ибо метка наша будет у автосалона Grotti Car's.


if(!strcmp(cmdtext, "/grotti"))
{
DisablePlayerRaceCheckpoint(playerid); // См. примечание 1 в конце темы.
SetPlayerRaceCheckpoint(playerid, 1, 559.0508,-1289.5999,17.2482, 559.0508,-1289.5999,17.2482, 6.0);
SendClientMessage(playerid, -1, "Метка-указатель была установлена.");
return 1;
}

Ну и далее, как и в случае с нашей предыдущей целью, проверим нахождение игрока в нашей метке, на этот раз другим пабликом:


public OnPlayerEnterRaceCheckpoint(playerid)
{
if(IsPlayerInRangeOfPoint(playerid, 6.0, 559.0508,-1289.5999,17.2482))
{
DisablePlayerRaceCheckpoint(playerid);
SendClientMessage(playerid, -1, "Метка-указатель достигнута!");
}
return 1;
}

Вот и все =)


Заключение

Я рассказал и показал вам все основные функции чекпоинтов, для чего их можно использовать, а также привел пару полезных примеров. К сожалению в моем уроке нет примера использования некоторых функций и колбэков, но я думаю вы сами сможете понять (по описанию) для чего они нужны. Все примеры, которые я предоставил для вас, предназначены для более ясного понимания как задействовать "метки" в деле. На этом все. Удачи.


P.S Вы могли заметить в примерах ссылки на примечания в конце темы. Я не забыл про это, сейчас я опишу вам пару нюансов работы с чекпоинтами.

В SA:MP существует небольшой баг с диаметрами чекпоинтов. Если у игрока установлен чекпоинт и ему сразу установить новый чекпоинт, размер новой метки будет соответствовать старой, для этого мы перед установкой метки, скрываем старую.

В отличие от стримера, стандартные чекпоинты SA:MP, нельзя определить по ID. Для того чтобы определять, находится ли игрок в нужном нам чекпоинте, я советую вам использовать проверку координат игрока.

У чекпоинтов координата Z устанавливается не всегда верно, поэтому возможны погрешности в установке чекпоинтов в различных самописных интерьерах.


Урок подготовил: wAx
В уроке используется материал взятый с http://www.wiki.sa-mp.com

underwoker
21.07.2014, 18:42
Еще было бы не плохо дописать:
Что в интерьерах с 0, добавить чекпоинты не получится, т.к. у них нет Z координаты.

Osetin
24.07.2014, 10:56
Неплохой урок.

wAx
11.09.2014, 21:00
Еще было бы не плохо дописать:
Что в интерьерах с 0, добавить чекпоинты не получится, т.к. у них нет Z координаты.
Не отвечал сразу на данный пост, по скольку сам не сталкивался, вот теперь отвечу..

Вполне можно добавить чекпоинт (стример), но вот координата z, действительно устанавливается неверно, в итоге чекпоинт есть, на него можно встать, но он наполовину в воздухе. Как-то так..

Salvacore
11.09.2014, 21:09
Не отвечал сразу на данный пост, по скольку сам не сталкивался, вот теперь отвечу..

Вполне можно добавить чекпоинт (стример), но вот координата z, действительно устанавливается неверно, в итоге чекпоинт есть, на него можно встать, но он наполовину в воздухе. Как-то так..
MapAndreas