Привет! Если вы читаете это - вы еще не зарегистрированы. Это займет не больше минуты. Нажмите здесь, чтобы пройти регистрацию в несколько простых шагов, чтобы получить доступ ко всем разделам нашего форума. Удачи!
Суть системы: игрок может лазать по лестницам и стенам, по любым поверхностям и вообще везде, где вы захотите. Реализовано в виде связки анимций, телепорта и работы с текстдравами. Пока готовится к релизу мой ФС, решил накидать такое решение, чтобы потом не было вопросов типа: "как добавить ещё лестницы?", "как выставить угол?" и т.п. Конструктив системы был взят с моего решения Chinatown Wars Teleport.
Для начала создадим необходимые переменные. У нас это связка текстдравов и координаты одной из поверхностей.
new Text:BlackScreen[6], Float:LadderCoords[2][4] = {
{-1844.9794, 581.0343, 35.1683, 237.8849}, // подножие поверхности
{-1844.0436, 580.2306, 242.0142, 237.8849} // конечная точка
};
Как вы видите, угол поворота игрока тоже включён в массив. Пренебрегать им крайне не рекомендуется, т.к. сама система распределения поворотов и анимаций строится именно на нём.
Создадим текстдравы, элементы которых мы обозначили выше. На всякий пожарный добавил пикап с инфой (здание находится в СФ - с чёрными стенами, возле Cluckin' Bell):
Кому нужно - напишите отдельный код выгрузки текстдравов, пикапа и 3д-текста.
Теперь самое интересное. У меня начало движения начинается по нажатию клавиши (можете сделать и команду).
if(newkeys & KEY_WALK) // если клавиша - идти пешком
{
for(new i = 0; i < sizeof(LadderCoords); i++) // пробегаемся по массиву с координатами
{
if(IsPlayerInRangeOfPoint(playerid, 1, LadderCoords[i][0], LadderCoords[i][1], LadderCoords[i][2])) // если находимся в радиусе ближайших координат
{
SetPlayerPos(playerid, LadderCoords[i][0], LadderCoords[i][1], LadderCoords[i][2]); // выравниваем позицию
SetCameraBehindPlayer(playerid); // сбрасываем камеру
SetPVarInt(playerid, "Iteration", 15); // выставляем задержку перед телепортом на конечные координаты
SetTimerEx("Ladder", 100, 0, "i", playerid); // запускаем систему подъёма
SetPVarInt(playerid, "LadderID", i); // указываем порядковый номер лестницы/поверхности
break; // обрываем цикл, т.к. ближайшие координаты найдены и нужные нам действия уже выполняются
}
}
}
Ну и сами управляющие таймеры:
forward Ladder(playerid);
public Ladder(playerid)
{
new iter = GetPVarInt(playerid, "Iteration"), ladderid = GetPVarInt(playerid, "LadderID");
if(iter > 0)
{
switch(iter)
{
case 12:
{
new Float:a;
GetPlayerFacingAngle(playerid, a);
if(a > LadderCoords[ladderid][3] - 181.0 && a < LadderCoords[ladderid][3] + 1.0) // если угол в правую сторону
{
SetPlayerFacingAngle(playerid, LadderCoords[ladderid][3] + 90.0); // выставляем нужный угол для адекватной анимации
ApplyAnimation(playerid, "DOZER", "DOZER_Align_LHS", 3.5, 0, 1, 1, 1, 1000, 1);
}
else
{
SetPlayerFacingAngle(playerid, LadderCoords[ladderid][3] - 90.0);
ApplyAnimation(playerid, "DOZER", "DOZER_Align_RHS", 3.5, 0, 1, 1, 1, 1000, 1);
}
SetTimerEx("NoAnim", 1000, 0, "i", playerid); // выставляем таймер сброса анимации, чтобы не было фриза по её окончанию
}
case 6: TextDrawShowForPlayer(playerid, BlackScreen[0]); // отсюда начинается затемнение экрана текстдравами
case 5:
{
TextDrawHideForPlayer(playerid, BlackScreen[0]);
TextDrawShowForPlayer(playerid, BlackScreen[1]);
}
case 4:
{
TextDrawHideForPlayer(playerid, BlackScreen[1]);
TextDrawShowForPlayer(playerid, BlackScreen[2]);
}
case 3:
{
TextDrawHideForPlayer(playerid, BlackScreen[2]);
TextDrawShowForPlayer(playerid, BlackScreen[3]);
}
case 2:
{
TextDrawHideForPlayer(playerid, BlackScreen[3]);
TextDrawShowForPlayer(playerid, BlackScreen[4]);
}
case 1:
{
TextDrawHideForPlayer(playerid, BlackScreen[4]);
TextDrawShowForPlayer(playerid, BlackScreen[5]);
SetPlayerPos(playerid, LadderCoords[ladderid + 1][0], LadderCoords[ladderid + 1][1], LadderCoords[ladderid + 1][2]); // Выставляем игроку конечную позицию
}
}
SetPVarInt(playerid, "Iteration", iter - 1); // понижаем итерацию (круг обхода таймера)
SetTimerEx("Ladder", 100, 0, "i", playerid); // заново запускаем таймер
}
else if(iter == 0) // если итерации закончились
{
SetPlayerFacingAngle(playerid, LadderCoords[ladderid][3]); // выставляем нужный угол (обычно такой же, как и в начальной точке)
TextDrawHideForPlayer(playerid, BlackScreen[5]); // прячем текстдрав
ApplyAnimation(playerid, "PED", "CLIMB_Stand", 4.1, 0, 1, 1, 1, 1000, 1); // проигрываем конечную анимацию
SetTimerEx("NoAnim", 500, 0, "i", playerid); // выставляем таймер очистки анимации
DeletePVar(playerid, "LadderID"); // Удаляем ненужные PVar'ы
DeletePVar(playerid, "Iteration");
}
return 1;
}
forward NoAnim(playerid);
public NoAnim(playerid) return ClearAnimations(playerid);
Вот и вся система. Аналогов, особенного такого уровня, не существует.