PDA

Просмотр полной версии : [Мануал] Уникальный телепорт администрации



whale
03.06.2017, 22:00
Доброго времени суток, уважаемые пользователи портала Pro-Pawn.
Сегодня я хотел бы представить Вам недавно написанную мной работу - телепорт для администрации.
Но, телепорт весьма необычный.


В чём особенность системы?:
— Использование динамических зон (streamer).
— Полная автоматизация работы.
— От Вас требуется только занести новые данные в массив.

— Важно: код не рассчитан на новичков. Комментарии и объяснения в данной теме будут, но разжёвывать каждую строку кода - слишком кропотливое занятие, знаете ли.

— Принцип работы системы:

1. Создаётся динамическая прямоугольная зона (CreateDynamicRectangle)
Примечание: для получения минимальных и максимальных координат рекомендую использовать данную программу (SAMP Zone Editor): Жми меня (http://pro-pawn.ru/showthread.php?7280-SAMP-Zone-Editor)

2. Когда игрок входит в динамическую зону (OnPlayerEnterDynamicArea) - с помощью foreach перебираются все зоны из итератора - соответственно инкрементируется переменная, которая хранит количество игроков в указанной зоне. После чего идёт проверка - имеет ли зона статус "зелёной" (anti-dm zone). Если зона такова - переменной игрока (p_green_zone_status[MAX_PLAYERS char]) присваивается значение 1 (т.е игрок находится в "зелёной" зоне).

С выходом из зоны всё аналогично.

3. Если игрок пытается стрелять в "зелёной" зоне - ему 2 раза выводится предупреждение и его замораживает, на 3-й раз игрока отключает от сервера.

4. А что касаемо самого диалогового окна: в первом отображаются разделы, во втором - зоны, которые относятся к указанному разделу. Помимо их наименований указывается расстояние до точки телепорта (x,y,z), количество игроков в данной зоне и является ли зона "зелёной" (anti-dm zone).

Надеюсь, что принцип работы я объяснил доступно.
Так же рекомендую посмотреть несколько скриншотов ниже, после чего мы перейдём непосредственно к коду.



https://s8.hostingkartinok.com/uploads/images/2017/06/79271fc3ed34f2bf332c82558353823c.png (https://hostingkartinok.com/show-image.php?id=79271fc3ed34f2bf332c82558353823c)

https://s8.hostingkartinok.com/uploads/images/2017/06/bc0f866707bb929420a8d2de53db0b1e.png (https://hostingkartinok.com/show-image.php?id=bc0f866707bb929420a8d2de53db0b1e)

https://s8.hostingkartinok.com/uploads/images/2017/06/e7b3ac158f4589c1fdf35b34bbff835d.png (https://hostingkartinok.com/show-image.php?id=e7b3ac158f4589c1fdf35b34bbff835d)

https://s8.hostingkartinok.com/uploads/images/2017/06/2927aabdca16379dec0fba24db946b75.png (https://hostingkartinok.com/show-image.php?id=2927aabdca16379dec0fba24db946b75)

— Перейдём непосредственно к коду.

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

const
MAX_ADMIN_TELEPORTS = 2, // Максимальное количество телепортов. При добавлении нового телепорта инкрементируйте данное значение (добавляйте +1 к значению).
MAX_ADMIN_TELEPORT_NAME = 17, // Максимальное количество символов в названии телепорта
MAX_AT_SECTIONS_NAME = 28; // Максимальное количество символов в названии раздела телепортов

Так же рекомендую создать enum для названий диалогов, дабы не путать их. Либо же представить их как макросы:



enum e_DIALOG_IDS
{
dAdmin_TpMenu_Main,
dAdmin_TpMenu_PopularPlaces
};



#define dAdmin_TpMenu_Main 1
#define dAdmin_TpMenu_PopularPlaces 2



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

enum e_ADMIN_TELEPORT_INFO
{
atDynamicArea, // Идентификатор динамической зоны
atNumberOfPlayers // Количество игроков в динамической зоне
};
new atInfo[MAX_ADMIN_TELEPORTS][e_ADMIN_TELEPORT_INFO];

Для дальнейшего использования нам понадобится ещё один enum, который будет хранить в себе перечисление типов для разделов и, собственно говоря, массив, который мы будем заполнять данной информацией (названия "разделов"):


enum _:e_AT_SECTIONS_INFO
{
POPULAR_PLACES
};

new atSectionsInfo[e_AT_SECTIONS_INFO][MAX_AT_SECTIONS_NAME] =
{
// В данный массив, при добавлении разделов, записывайте их названия
{"Часто посещаемые места"}
};

Ну и, по сути, основная часть данного кода - enum, который будет заполняться данными о динамической зоне из массива и сам массив:

enum e_ADMIN_TELEPORT_AREAS_INFO
{
atType, // Тип телепорта (зоны). Пример: POPULAR_PLACES
atName[MAX_ADMIN_TELEPORT_NAME], // Название зоны, которые будет указано в диалоговом окне
atSecondName[MAX_ADMIN_TELEPORT_NAME], // Название зоны, которое будет указано при входе в зону

Float:atTelepPosX, // Координата X для телепорта
Float:atTelepPosY, // Координата Y для телепорта
Float:atTelepPosZ, // Координата Z для телепорта
Float:atTelepPosA, // Угол поворота для телепорта

Float:atMinPosX, // Минимальная координата X
Float:atMinPosY, // Минимальная координата Y
Float:atMaxPosX, // Максимальная координата X
Float:atMaxPosY, // Максимальная координата Y

atTelepVirtualWorld, // Виртуальный мир, который распостранится на динамическую зону
atTelepInterior, // Интерьер динамической зоны

atGreenZone // "Зелёная" (anti-dm) зона. Значения: 0 и 1. 0 - зона не является "зелёной". 1 - зона является "зелёной".
};

// В массив ниже Вы и будете заносить новые данные :)
new atData[MAX_ADMIN_TELEPORTS][e_ADMIN_TELEPORT_AREAS_INFO] =
// Желательно придерживаться табличного вида, дабы самим потом было проще ориентироваться в массиве (на форуме этот код, скорее всего, превратится в кашу, но суть в том, чтоб все данные разделить по своим колонкам)
// Ну, а если Вы видите данный код не "кашей" - значит я убил много времени, чтобы его отредактировать :)
{
// atType atName atSecondName tpX tpY tpZ tpA min_posX min_posY max_posX max_posY VW Int GZ
{POPULAR_PLACES, "Мэрия LS", "Мэрии LS", 1480.9125, -1723.8544, 13.5469, 179.5673, 1433.0, -1599.0, 1529.0, -1759.0, 0, 0, 1},
{POPULAR_PLACES, "ЖДЛС", "ЖДЛС", 1581.7778, -1618.1624, 13.3828, 192.1007, 1810.7983, -1881.51780, 1759.7397, -1942.9968, 0, 0, 1}
};

И последнее, что мы объявим в данном мануале - итератор и переменную:

new
Iterator:AdminTeleportAreas<MAX_ADMIN_TELEPORTS>, // Итератор, в котором хранятся созданые динамические зоны
p_green_zone_status[MAX_PLAYERS char];

— Паблики, стоки, команды...

Теперь, когда мы закончили объявлять всё, что нам нужно, - перейдём непосредственно к использованию "этого всего".
С данного момента комментариев будет гораздо меньше, так как разжёвывать каждую строку кода - достаточно нудное занятие. А если учесть, что система, скажем так, не рассчитана на "ньюфагов" (как было написано выше) - так тем более.

Для начала разберёмся с public OnGameModeInit(). В данный паблик мы поместим загрузку наших динамических зон.
(Под спойлером так же будет stock-функция, которую мы вызываем в public OnGameModeInit())
Сам stock с загрузкой динамических зон, собственно, Вы можете поместить в конец мода, либо в другое, удобное для Вас место.



public OnGameModeInit()
{
LoadAdminTeleports(); // Загружаем динамические зоны при запуске сервера
return 1;
}



stock LoadAdminTeleports()
{
for(new i; i < MAX_ADMIN_TELEPORTS; i++)
{
Iter_Add(AdminTeleportAreas, i);

atInfo[i][atDynamicArea] = CreateDynamicRectangle(atData[i][atMinPosX], atData[i][atMinPosY], atData[i][atMaxPosX], atData[i][atMaxPosY], 0, 0, -1);
}
printf("TOTAL_ADMIN_AREAS_LOADED: %d\n", Iter_Count(AdminTeleportAreas));
return 1;
}



Далее мы рассмотрим 2 паблика: OnPlayerEnterDynamicArea и OnPlayerLeaveDynamicArea:



public OnPlayerEnterDynamicArea(playerid, areaid) // Когда игрок входит в динамическую зону
{
foreach(new i: AdminTeleportAreas) // Перебираем все созданные нами зоны
{
if(areaid == atInfo[i][atDynamicArea]) // Если идентификатор динамической зоны совпадает с одним из идентификатором наших зон - идём дальше
{
atInfo[i][atNumberOfPlayers]++; // Инкрементируем количество игроков в указанной динамической зоне

if(atData[i][atGreenZone] == 1) // Если зона, в которую вошёл игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 1; // Устанавливаем игроку статус "находится в зелёной зоне"
SetPVarInt(playerid, "damage_in_green_zone", 0); // Устанавливаем игроку количество попыток нанести урон в "зелёной зоне" на 0
}
return 1;
}
}
return 1;
}



public OnPlayerLeaveDynamicArea(playerid, areaid) // Когда игрок покидает динамическую зону
{
foreach(new i: AdminTeleportAreas) // Перебираем все созданные нами зоны
{
if(areaid == atInfo[i][atDynamicArea]) // Если идентификатор динамической зоны совпадает с одним из идентификатором наших зон - идём дальше
{
atInfo[i][atNumberOfPlayers]--; // Декрементируем количество игроков в указанной динамической зоне

if(atData[i][atGreenZone] == 1) // Если зона, из которой вышел игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 0; // Устанавливаем игроку статус "не находится в зелёной зоне"
DeletePVar(playerid, "damage_in_green_zone"); // Удаляем PVar с информацией о количестве попыток нанести урон в "зелёной зоне"
}
return 1;
}
}
return 1;
}



Далее мы так же рассмотрим public OnPlayerWeaponShot - когда игрок стреляет из оружия:


public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
if(p_green_zone_status{playerid} == 1) // Если игрок находится в "зелёной зоне"
{
if(GetPVarInt(playerid, "damage_in_green_zone") < 2) // Если попыток нанести урон игрокам меньше 2 (0 или 1)
{
SendClientMessage(playerid, -1, !"SERVER: На данной территории запрещено использовать оружие!"); // Выводим игроку предупреждение
TogglePlayerControllable(playerid, false); // Отключаем игркоу управление персонажем

SetTimerEx("UnFreezePlayer", 3500, false, "d", playerid); // Запускаем таймер для "разморозки" игрока на 3500мс (3.5 секунд)
SetPVarInt(playerid, "damage_in_green_zone", GetPVarInt(playerid, "damage_in_green_zone")+1); // Инкрементируем количество попыток нанести урон
}
else // Если же количество попыток нанести урон == 2 (тоесть это уже будет 3 попытка)
{
SendClientMessage(playerid, -1, !"Вы были кикнуты. Причина: многократное использование оружия в зелёных зонах!"); // Выводим игроку предупреждение о том, что он был кикнут
Kick(playerid); // Кикаем игрока
}
}
return 1;
}

forward UnFreezePlayer(playerid);
public UnFreezePlayer(playerid) // Паблик "разморозки" игрока
return TogglePlayerControllable(playerid, true);


Теперь можно перейти к самой команде, ради которой, по сути, всё это и было затеяно:


CMD:teleport(playerid, params[])
{
ShowAdminTeleportDialog(playerid);
return 1;
}
stock ShowAdminTeleportDialog(playerid)
{
DeletePVar(playerid, "atSectionID");

new
dialog_string[(3+sizeof(atSectionsInfo[]))*sizeof(atSectionsInfo)+1];

for(new i; i < sizeof(atSectionsInfo); i++)
{
format(dialog_string, sizeof(dialog_string), "%s— %s\n", dialog_string, atSectionsInfo[i]);
}
ShowPlayerDialog(playerid, dAdmin_TpMenu_Main, DIALOG_STYLE_LIST, "Телепорт администрации", dialog_string, "Выбрать", "Отмена");
return 1;
}


Ну и, наконец-то мы подходим к концу. Осталось лишь разобраться с самими диалогами - public OnDialogResponse:
- Примечание: в данном мануале рассматривается вариант со switch-ветвлением, а не условиями if / else.


public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case dAdmin_TpMenu_Main:
{
if(!response)
return 1;

SetPVarInt(playerid, "atSectionID", listitem);

static
dialog_string[(63+MAX_ADMIN_TELEPORT_NAME+(11+3)+3)*MAX_ADMIN_TELEPORTS+1],
header_string[30+sizeof(atSectionsInfo[])+1];

dialog_string = "Наименование\tРасстояние до точки\tИгроков\tЗелёная зона\n";//44
for(new i; i < MAX_ADMIN_TELEPORTS; i++)
{
if(atData[i][atType] != listitem)
continue;

format(dialog_string, sizeof(dialog_string), "%s%s\t%.2fм\t%d\t%s\n",
dialog_string,
atData[i][atName],
GetPlayerDistanceFromPoint(playerid, atData[i][atTelepPosX], atData[i][atTelepPosY], atData[i][atTelepPosZ]),
atInfo[i][atNumberOfPlayers], (atData[i][atGreenZone] ? "Да" : "Нет"));
}
header_string = "Телепорт администрации: ";
strcat(header_string, atSectionsInfo[listitem]);
ShowPlayerDialog(playerid, dAdmin_TpMenu_PopularPlaces, DIALOG_STYLE_TABLIST_HEADERS, header_string, dialog_string, "Выбрать", "Назад");
return 1;
}
case dAdmin_TpMenu_PopularPlaces:
{
if(!response)
return ShowAdminTeleportDialog(playerid);

for(new i, num; i < MAX_ADMIN_TELEPORTS; i++)
{
if(atData[i][atType] != GetPVarInt(playerid, "atSectionID"))
continue;

if(num++ == listitem)
{
SetPlayerPosEx(playerid, atData[i][atTelepPosX], atData[i][atTelepPosY], atData[i][atTelepPosZ]);
if(floatcmp(atData[i][atTelepPosA], 0.0) == 1)
{
SetPlayerFacingAngle(playerid, atData[i][atTelepPosA]);
}
SetCameraBehindPlayer(playerid);
break;
}
}
return 1;
}
}
return 1;
}


Полный код (pastebin): https://pastebin.com/HxUvBeiN

Всех, кто уделил своё личное время и прочёл данную тему до конца - благодарю за внимание :)
Надеюсь, что я ничего не забыл и написал всё, что хотел.

P.S Это моя первая тема на данном портале и первый мануал с подобным объёмом. Так что, очень прошу не сильно ругаться/кричать, если заметите какие-либо недочёты. Так же жду комментариев, адекватной, обоснованной критики и помощи.

Ещё раз благодарю за внимание.


Так же благодарность за помощь с некоторыми участками кода выражаю: DeIMoS`у

https://pp.userapi.com/c639116/v639116410/29f7b/qqFTi1ZLnfs.jpg
Обновление от 04.06.2017: Релиз include-версии.
Download (include): https://yadi.sk/d/fyrfBkyq3JoHUe

DeimoS
03.06.2017, 22:40
Так это телепорт для админов или анти-дм зоны? :)

И на данном форуме никто никогда сильно не "кричит/ругается". Только лишь по делу :)

whale
03.06.2017, 22:45
Так это телепорт для админов или анти-дм зоны? :)

И на данном форуме никто никогда сильно не "кричит/ругается". Только лишь по делу :)

Изначальная задумка была как телепорт для администрации, но, после того как я опубликовал первую версию данной системы на g-i - я решил немного усовершенствовать данную систему :)

Я просто так выразился :)
Наоборот буду очень рад комментариям и критике, так что, готов выслушивать всё (надо же как-нибудь самосовершенствоваться, не так ли?):acute:

upd: и да, кстати, я послушал твой совет и вместо CreateDynamicCircle использовал CreateDynamicRectangle :)

DeimoS
03.06.2017, 22:58
Изначальная задумка была как телепорт для администрации, но, после того как я опубликовал первую версию данной системы на g-i - я решил немного усовершенствовать данную систему :)

Ну намешивать в одной системе кучу функционала - не всегда хорошая идея, ибо не всем он нужен.
Стоило хотя бы добавить возможность отключения телепортов/зелёных зон прямо при компиляции (при помощи макросов) + для каждого конкретного телепорта непосредственно, чтоб можно было, например, в одном случае отключить телепорт, но создать зону, во втором - отключить зону, но создать телепорт, а в третьем - создать и зону, и телепорт. Тогда функциональность будет оправдана.


и да, кстати, я послушал твой совет и вместо динамического "круга" переделал систему под создание в виде прямоугольника :)

Ну только не добавил возможность создавать её прямо из игры, настраивая координаты при помощи клавиш и гангзоны :mamba:

Long-
03.06.2017, 23:12
— Важно: код не рассчитан на новичков. Комментарии и объяснения в данной теме будут, но разжёвывать каждую строку кода - слишком кропотливое занятие, знаете ли.

DeimoS'a с его регистрацией это не остановило:blush2::blush2::dirol:


const
dAdmin_TpMenu_Main = 1,
dAdmin_TpMenu_PopularPlaces = 2;

:D :D
Если ты про то что я писал на g-i , то что добавь 3-ий вариант, я пошутил :D
Имена констант должны быть все заглавными буквами.

whale
03.06.2017, 23:12
Ну намешивать в одной системе кучу функционала - не всегда хорошая идея, ибо не всем он нужен.
Стоило хотя бы добавить возможность отключения телепортов/зелёных зон прямо при компиляции (при помощи макросов) + для каждого конкретного телепорта непосредственно, чтоб можно было, например, в одном случае отключить телепорт, но создать зону, во втором - отключить зону, но создать телепорт, а в третьем - создать и зону, и телепорт. Тогда функциональность будет оправдана.



Ну только не добавил возможность создавать её прямо из игры, настраивая координаты при помощи клавиш и гангзоны :mamba:

Мне приходит идея замакросить значения (к примеру):

#define AT_ONLY_TELEPORT 1
#define AT_ONLY_DYNAMICAREA 2
#define AT_TELEPORT_AND_DYNAMICAREA 3
(Добавить ещё одно значение в массив с данными)

И во время загрузки зоны (LoadAdminTeleports()) сделать switch-ветвление по данным типам.
Или же есть другие варианты? (Пре-процессор, к примеру???)

- - - Добавлено - - -


DeimoS'a с его регистрацией это не остановило:blush2::blush2::dirol:

Но и я не на уровне DeIMoS`а, дабы исполнять что-то подобное :boredom:.

Long-
03.06.2017, 23:20
Что? есть вроде вики, оно разрешено всем, скопировать от туда параметры не составит труда, ну это я так к слову.
Лучше бы эту систему выложил в виде инклуда, или FS'a, по-моему с таким функционалом оно туда больше идет.
И почему рекомендацию по PAWN от DC на счет энуменатора ты принял, а такую как "Имена констант и глобальных переменных пишутся заглавными буквами", нет?)

И почему некоторые этот портал воспринимают как будто тут боги сидят?)
Здесь такие же люди которые тебя не укусят, а только натолкнут на хорошие мысли, просто уровень знаний больше чем у нас.
И как будто если не написать "Так что, очень прошу не сильно ругаться/кричать, если заметите какие-либо недочёты.", тебя убьют нахер))

DeimoS
03.06.2017, 23:25
Мне приходит идея замакросить значения (к примеру):

#define AT_ONLY_TELEPORT 1
#define AT_ONLY_DYNAMICAREA 2
#define AT_TELEPORT_AND_DYNAMICAREA 3
(Добавить ещё одно значение в массив с данными)

И во время загрузки зоны (LoadAdminTeleports()) сделать switch-ветвление по данным типам.
Или же есть другие варианты? (Пре-процессор, к примеру???)

Изначально всё реализовать в виде инклуда с перехватами и добавить проверки, типа


#if !defined ПРЕФИКС_DISABLE_TELEPORT
//код телепортов
#endif
#if !defined ПРЕФИКС_DISABLE_GREENZONES
//Код зз
#endif
И тогда если нужен полный функционал - не нужно будет прописывать ничего лишнего, кроме, собственно, подключения инклуда. Иначе просто перед инклудом

#define ПРЕФИКС_DISABLE_TELEPORT // отключает телепорты

Но тогда стоит добавить кучу дополнительного функционала, типа коллбэка для тех, кто ДМить в ЗЗ, дабы каждый сам смог настраивать наказания. В общем, превратить весь этот код в полноценный редактор, который способен создавать зелёные зоны/телепорты

whale
03.06.2017, 23:26
Что? есть вроде вики, оно разрешено всем, скопировать от туда параметры не составит труда, ну это я так к слову.
Лучше бы эту систему выложил в виде инклуда, или FS'a, по-моему с таким функционалом оно туда больше идет.
И почему рекомендацию по PAWN от DC на счет энуменатора ты принял, а такую как "Имена констант и глобальных переменных пишутся заглавными буквами", нет?)

Почему же? Константы, у меня, вроде как, все написаны заглавными буквами. А насчёт переменной p_green_zone_status[MAX_PLAYERS char] - не удобно писать одну заглавную 'P' постоянно. Перечитаю ещё раз рекомендации от DC.

- - - Добавлено - - -


Изначально всё реализовать в виде инклуда с перехватами и добавить проверки, типа


#if !defined ПРЕФИКС_DISABLE_TELEPORT
//код телепортов
#endif
#if !defined ПРЕФИКС_DISABLE_GREENZONES
//Код зз
#endif
И тогда если нужен полный функционал - не нужно будет прописывать ничего лишнего, кроме, собственно, подключения инклуда. Иначе просто перед инклудом

#define ПРЕФИКС_DISABLE_TELEPORT // отключает телепорты

Но тогда стоит добавить кучу дополнительного функционала, типа коллбэка для тех, кто ДМить в ЗЗ, дабы каждый сам смог настраивать наказания. В общем, превратить весь этот код в полноценный редактор, который способен создавать зелёные зоны/телепорты

Вот именно по этой причине я боюсь браться за это. Ибо я не особо хорошо знаком с перехватами и реализацией подобных систем в FS/Include.

Long-
03.06.2017, 23:32
Почему же? Константы, у меня, вроде как, все написаны заглавными буквами. А насчёт переменной p_green_zone_status[MAX_PLAYERS char] - не удобно писать одну заглавную 'P' постоянно. Перечитаю ещё раз рекомендации от DC.

- - - Добавлено - - -



Вот именно по этой причине я боюсь браться за это. Ибо я не особо хорошо знаком с перехватами и реализацией подобных систем в FS/Include.

Все заглавные - значит все буквы верхнего регистра до единой.


const
DADMIN_TPMENU_MAIN = 1,
DADMIN_TPMENU_POPULARPLACES = 2;

Да и обычно оператором "const" выделяют вроде как максимальное значение чего либо,я бы оставил просто энуменатор id диалогов, и варианты никакие не нужны.

(Хотел тебе +-ик поставить, но что-то не могу :(
Работа хорошая молодец.)

whale
03.06.2017, 23:37
Все заглавные - значит все буквы верхнего регистра до единой.


const
DADMIN_TPMENU_MAIN = 1,
DADMIN_TPMENU_POPULARPLACES = 2;

Да и обычно оператором "const" выделяют вроде как максимальное значение чего либо,я бы оставил просто энуменатор id диалогов, и варианты никакие не нужны.

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

Long-
03.06.2017, 23:40
"Все заглавные - значит все буквы верхнего регистра до единой." - в таком случае, не знаю, как для остальных, но, лично для меня, сильно падает читабельность кода.

Так у тебя вначале :


const
MAX_ADMIN_TELEPORTS = 2, // Максимальное количество телепортов. При добавлении нового телепорта инкрементируйте данное значение (добавляйте +1 к значению).
MAX_ADMIN_TELEPORT_NAME = 17, // Максимальное количество символов в названии телепорта
MAX_AT_SECTIONS_NAME = 28; // Максимальное количество символов в названии раздела телепортов

?? что тут не читабельного, так-же в предыдущим сообщение я оставил примечание: "Да и обычно оператором "const" выделяют вроде как максимальное значение чего либо,я бы оставил просто энуменатор id диалогов, и варианты никакие не нужны.", как у тебя это сделано сейчас.

whale
03.06.2017, 23:47
Так у тебя вначале :


const
MAX_ADMIN_TELEPORTS = 2, // Максимальное количество телепортов. При добавлении нового телепорта инкрементируйте данное значение (добавляйте +1 к значению).
MAX_ADMIN_TELEPORT_NAME = 17, // Максимальное количество символов в названии телепорта
MAX_AT_SECTIONS_NAME = 28; // Максимальное количество символов в названии раздела телепортов

?? что тут не читабельного, так-же в предыдущим сообщение я оставил примечание: "Да и обычно оператором "const" выделяют вроде как максимальное значение чего либо,я бы оставил просто энуменатор id диалогов, и варианты никакие не нужны.", как у тебя это сделано сейчас.

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

DeimoS
03.06.2017, 23:48
Вот именно по этой причине я боюсь браться за это. Ибо я не особо хорошо знаком с перехватами и реализацией подобных систем в FS/Include.

Ну так нужно ведь когда-нибудь учиться, не? :) Почему бы не начать?

whale
03.06.2017, 23:51
Ну так нужно ведь когда-нибудь учиться, не? :) Почему бы не начать?

Да, думаю, что самое время попробовать :)

Уже нашёл информацию от DC по поводу перехватов. Попробую освоить в ближайшее время, и, если всё будет благополучно - постараюсь реализовать твою задумку по поводу FS/Include :good2:

Upd: обновил первый пост (убрал вариант с константами для диалогов).

Long-
03.06.2017, 23:51
Да, думаю, что самое время попробовать :)

Уже нашёл информацию от DC по поводу перехватов. Попробую освоить в ближайшее время, и, если всё будет благополучно - постараюсь реализовать твою задумку по поводу FS/Include :good2:
Кстати лучше в FS , дабы просто подключить его и больше никаких действий не делать))

whale
03.06.2017, 23:54
Ето моя задумка(

Да, твоя тоже :dirol:
(Не заметил твой пост по этому поводу на первой странице, извиняюсь)

whale
04.06.2017, 04:56
Update: Релиз системы в include.
Ссылка на скачивание в первом посте.

P.S Сегодня осилил только знакомство с перехватами и написание include-версии.
P.S.S Возможно, в скором времени, при наличии времени, займусь реализацией обновлений (но это не точно :D)

execution
03.06.2019, 23:08
Мне кажется можно избежать циклов, когда игрок входит/выходит в динамическую зону (если создаются динамические зоны одновременно, то есть в данном случае)



public OnPlayerEnterDynamicArea(playerid, areaid) // Когда игрок входит в динамическую зону
{
if(atInfo[0][atDynamicArea] <= areaid <= atInfo[MAX_ADMIN_TELEPORTS - 1][atDynamicArea])
{
new
cout = areaid - atInfo[0][atDynamicArea];

atInfo[cout][atNumberOfPlayers]++; // Инкрементируем количество игроков в указанной динамической зоне

if(atData[cout][atGreenZone] == 1) // Если зона, в которую вошёл игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 1; // Устанавливаем игроку статус "находится в зелёной зоне"
SetPVarInt(playerid, "damage_in_green_zone", 0); // Устанавливаем игроку количество попыток нанести урон в "зелёной зоне" на 0
}

return 1;
}

return 1;
}

public OnPlayerLeaveDynamicArea(playerid, areaid) // Когда игрок покидает динамическую зону
{
if(atInfo[0][atDynamicArea] <= areaid <= atInfo[MAX_ADMIN_TELEPORTS - 1][atDynamicArea])
{
new
cout = areaid - atInfo[0][atDynamicArea];

atInfo[cout][atNumberOfPlayers]--; // Декрементируем количество игроков в указанной динамической зоне

if(atData[cout][atGreenZone] == 1) // Если зона, из которой вышел игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 0; // Устанавливаем игроку статус "не находится в зелёной зоне"
DeletePVar(playerid, "damage_in_green_zone"); // Удаляем PVar с информацией о количестве попыток нанести урон в "зелёной зоне"
}

return 1;
}

return 1;
}


Да и не совсем понятно зачем было создавать итератор, если ты их используешь лишь в данных пабликах :grin:

DeimoS
04.06.2019, 12:43
Мне кажется можно избежать циклов, когда игрок входит/выходит в динамическую зону (если создаются динамические зоны одновременно, то есть в данном случае)



public OnPlayerEnterDynamicArea(playerid, areaid) // Когда игрок входит в динамическую зону
{
if(atInfo[0][atDynamicArea] <= areaid <= atInfo[MAX_ADMIN_TELEPORTS - 1][atDynamicArea])
{
new
cout = areaid - atInfo[0][atDynamicArea];

atInfo[cout][atNumberOfPlayers]++; // Инкрементируем количество игроков в указанной динамической зоне

if(atData[cout][atGreenZone] == 1) // Если зона, в которую вошёл игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 1; // Устанавливаем игроку статус "находится в зелёной зоне"
SetPVarInt(playerid, "damage_in_green_zone", 0); // Устанавливаем игроку количество попыток нанести урон в "зелёной зоне" на 0
}

return 1;
}

return 1;
}

public OnPlayerLeaveDynamicArea(playerid, areaid) // Когда игрок покидает динамическую зону
{
if(atInfo[0][atDynamicArea] <= areaid <= atInfo[MAX_ADMIN_TELEPORTS - 1][atDynamicArea])
{
new
cout = areaid - atInfo[0][atDynamicArea];

atInfo[cout][atNumberOfPlayers]--; // Декрементируем количество игроков в указанной динамической зоне

if(atData[cout][atGreenZone] == 1) // Если зона, из которой вышел игрок, является "зелёной" (anti-dm)
{
p_green_zone_status{playerid} = 0; // Устанавливаем игроку статус "не находится в зелёной зоне"
DeletePVar(playerid, "damage_in_green_zone"); // Удаляем PVar с информацией о количестве попыток нанести урон в "зелёной зоне"
}

return 1;
}

return 1;
}


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


Да и не совсем понятно зачем было создавать итератор, если ты их используешь лишь в данных пабликах :grin:

Чтоб быстрее искать нужную зону?
Хотя вообще такое актуально только для ситуаций, когда зоны могут во время работы сервера удаляться. Если удаления нет, то можно обойтись обычным циклом.

execution
04.06.2019, 13:20
Чтоб быстрее искать нужную зону?


Я понимаю, я акцентировал внимание на то, что пользуется перебором данным итератором лишь в данных палбиках, а в других местах нет