PDA

Просмотр полной версии : [Include] ds_skinselector



DeimoS
09.10.2016, 00:35
Данный инклуд добавляет возможность создавать фильтры для стандартного выбора скинов


Данный инклуд "перехватывает" стандартный выбор скинов, позволяя управлять тем, какие скины будут отображаться при нажатии на кнопки выбора
("<<" и ">>")
Это позволяет создавать своеобразные фильтры (например, отображать только мужские или только женские скины), не создавая дополнительных текстдравов
(как это делается на большинстве серверов на данный момент).
Скины для фильтров хранятся в массивах и легко добавляются/изменяются.
Для управления фильтрами в инклуде присутствует приличный функционал.




Подключение:


Для работы инклуда не требуется никаких дополнительных библиотек.
Что-бы подключить инклуд, достаточно добавить в начало мода, после подключения "a_samp"

#include <ds_skinselector>

#include <a_samp>
#include <ds_skinselector>
//Тут остальные инклуды



Настройка:



Для удобства настройки некоторые данные вынесены в макросы:



Имя макроса
Значение по умолчанию
Описание макроса



MAX_REGISTERED_ID_FILTERS

10
В данном макросе указывается максимальное число фильтров, которые могут быть созданы одновременно.
ID фильтров начинаются с нуля, следовательно, по умолчанию доступны слоты с
"0" по "9".



MAX_REGISTERED_NAME_FILTERS


30


Максимальная длина для имени фильтров.




INVALID_SS_FILTER_ID


-1


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




Пример настройки:

#include <a_samp>

#define MAX_REGISTERED_ID_FILTERS 30// Увеличим число фильтров до 30
#define MAX_REGISTERED_NAME_FILTERS 14// Уменьшим максимальную длину имени фильтров до 14
#include <ds_skinselector>
//Тут остальные инклуды





Особенности работы:


Инклуд имеет довольно "хрупкую" структуру, так как вся его работа завязана на AddPlayerClass, которые создаются внутри него (точнее, на их суммарном количестве).
Поэтому:


Если в вашем моде присутствуют функции AddPlayerClass/AddPlayerClassEx, удалите их.
Любая лишняя единица данных функций заставит систему работать некорректно.

Так же в инклуде учтен переход к выбору скина при смерти (нажатие на F4) и с помощью ForceClassSelection.



Новый коллбэк:


OnPlayerSelectedSkin(playerid, classid)

Данный коллбэк является платформой для функций-обработчиков данных из OnDialogResponse.
Иными словами, он нужен лишь для того, чтоб Вы записывали в него определённые функции из инклуда.
Подробнее об этих функциях расскажу ниже.



Описание функций:



• Синтаксис


CreateNewSelectorFilter(filterskin_id, filter_name[], skins_array[])


• Описание

Данная функция создаёт (регистрирует в памяти) новый фильтр


• Возвращаемые значения:



1
| Фильтр успешно создан



INVALID_SS_FILTER_ID
| Создать фильтр не удалось (превышен лимит/указан невалидный или занятый ID)




• Параметры:



filterskin_id
Свободный ID фильтра



filter_name[]
Имя для фильтра (поддерживаются все символы)



skins_array[]
Массив, в котором перечислены скины для фильтра







• Синтаксис


CallSelectorFilterByID(skin_filter_id, skins_array[])


• Описание

Данная функция служит "сердцем" системы, обрабатывая данные OnPlayerRequestClass и адаптируя их под указанный фильтр.
Используется исключительно внутри коллбэка OnPlayerSelectedSkin.
При добавлении нового фильтра является обязательной.
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID


• Возвращаемые значения:



1
| В случае успешной обработки кода (фильтр создан и совпадает с тем, что включен у игрока)



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



skin_filter_id
ID фильтра для обработки



skins_array[]
Массив, в котором хранятся скины для фильтра



• Синтаксис


CallSelectorFilterByID(_filter_name[], skins_array[])


• Описание

Данная функция служит "сердцем" системы, обрабатывая данные OnPlayerRequestClass и адаптируя их под указанный фильтр.
Используется исключительно внутри коллбэка OnPlayerSelectedSkin.
При добавлении нового фильтра является обязательной.
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени


• Возвращаемые значения:



1
| В случае успешной обработки кода (фильтр создан и совпадает с тем, что включен у игрока)



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



_filter_name[]
Имя фильтра для обработки



skins_array[]
Массив, в котором хранятся скины для фильтра






• Синтаксис


SetDefaultSelectorFilter_ID(filterid)


• Описание

Функция изменяет фильтр по умолчанию (тот, который будет выдаваться игрокам при входе на сервер)
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID


• Возвращаемые значения:



ID фильтра
| Фильтр успешно изменён



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



filterid
ID фильтра для установки по умолчанию




• Синтаксис


SetDefaultSelectorFilter_Name(_filter_name[])


• Описание

Функция изменяет фильтр по умолчанию (тот, который будет выдаваться игрокам при входе на сервер)
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени


• Возвращаемые значения:



ID фильтра
| Фильтр успешно изменён



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



_filter_name[]
Имя фильтра для установки по умолчанию






• Синтаксис


GetDefaultSelectorFilter();


• Описание

Функция возвращает ID фильтра, установленного по умолчанию


• Возвращаемые значения:


ID фильтра




• Параметры:


---






• Синтаксис


DeleteSelectorFilter_ID(filterid)


• Описание

Функция удаляет указанный фильтр.*
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID

* Массив со скинами, при использовании функции, не удаляется/отчищается. Функция лишь освобождает слот от фильтра



• Возвращаемые значения:



ID фильтра
| Фильтр успешно удалён



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



filterid
ID фильтра для удаления



• Синтаксис


DeleteSelectorFilter_Name(_filter_name[])


• Описание

Функция удаляет указанный фильтр.*
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени

* Массив со скинами, при использовании функции, не удаляется/отчищается. Функция лишь освобождает слот от фильтра



• Возвращаемые значения:



ID фильтра
| Фильтр успешно удалён



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



_filter_name[]
Имя фильтра для удаления






• Синтаксис


GetSelectorFilterID(filterid)


• Описание

Функция производит поиск указанного фильтра среди созданных.
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID


• Возвращаемые значения:



Имя фильтра,
который находится под указанным ID
| Фильтр существует



"Error"
| Фильтр не найден




• Параметры:



filterid
ID фильтра для поиска



• Синтаксис


GetSelectorFilterName(_filter_name[])


• Описание

Функция производит поиск указанного фильтра среди созданных.
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени


• Возвращаемые значения:



ID фильтра,
в котором записано указанное имя
| Фильтр существует



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



_filter_name[]
Имя фильтра для поиска






• Синтаксис


IsSelectorFilterValid_ID(filterid)


• Описание

Функция проверяет существование (валидность) фильтра.
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID


• Возвращаемые значения:



1
| Фильтр существует



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



filterid
ID фильтра для поиска



• Синтаксис


IsSelectorFilterValid_Name(_filter_name[])


• Описание

Функция проверяет существование (валидность) фильтра.
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени


• Возвращаемые значения:



1
| Фильтр существует



INVALID_SS_FILTER_ID
| Фильтр не найден




• Параметры:



_filter_name[]
Имя фильтра для поиска






• Синтаксис


SetSelectorFilterForPlayer_ID(playerid, filterid, skins_array[])


• Описание

Функция позволяет изменить ID фильтра для игрока
Отличается от следующей функции тем, что нужный фильтр указывается в виде ID


• Возвращаемые значения:



1
| Фильтр успешно изменён



INVALID_SS_FILTER_ID
| Произошла ошибка (игрок оффлайн/фильтр не существует и т.п.)




• Параметры:



playerid
ID игрока, которому нужно изменить фильтр



filterid
ID фильтра, который нужно установить игроку



skins_array[]
Массив, в котором хранятся скины для фильтра



• Синтаксис


SetSelectorFilterForPlayer_Name(playerid, _filter_name[], skins_array[])


• Описание

Функция позволяет изменить ID фильтра для игрока
Отличается от предыдущей функции тем, что нужный фильтр указывается в виде имени


• Возвращаемые значения:



1
| Фильтр успешно изменён



INVALID_SS_FILTER_ID
| Произошла ошибка (игрок оффлайн/фильтр не существует и т.п.)




• Параметры:



playerid
ID игрока, которому нужно изменить фильтр



_filter_name[]
Имя фильтра, который нужно установить игроку



skins_array[]
Массив, в котором хранятся скины для фильтра






• Синтаксис


GetSelectorFilterForPlayer(playerid)


• Описание

Функция позволяет узнать ID фильтра, который установлен у игрока


• Возвращаемые значения:



ID фильтра
| Игрок онлайн



INVALID_SS_FILTER_ID
| Игрок оффлайн




• Параметры:



playerid
ID игрока, фильтр которого нужно узнать






• Синтаксис


GetSelectorFilterFreeID()


• Описание

Функция возвращает первый свободный слот для фильтра


• Возвращаемые значения:


ID фильтра




• Параметры:


---





*Примечание:
Описание данных функций продублировано внутри самого инклуда





Примеры использования:


Начало мода:

#include <a_samp>
#include <other\ds_skinselector>

//Все скины (74 скина в SA-MP не существует, поэтому он закомментирован)
new all_skins[] =
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, /*74,*/ 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
311
};

//Все женские скины
new female_skins[] =
{
9, 10, 11, 12, 13, 31, 39, 40, 41, 53, 54, 55, 56, 63,
64, 65, 69, 75, 76, 77, 85, 87, 88, 89, 90, 91, 92, 93,
129, 130, 131, 132, 138, 139, 140, 141, 145, 148, 150,
151, 152, 157, 169, 172, 178, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199, 201, 205, 207, 211, 214, 215,
216, 218, 219, 224, 225, 226, 231, 232, 233, 237, 238,
243, 244, 245, 246, 251, 256, 257, 263, 298, 306, 307,
308, 309
};

//Все мужские скины (74 скина в SA-MP не существует, поэтому он закомментирован)
new male_skins[] =
{
1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34,
35, 36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 57, 58, 59, 60, 61, 62, 66, 67, 68, 70, 71,
72, 73, /*74,*/ 78, 79, 80, 81, 82, 83, 84, 86, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
127, 128, 133, 134, 135, 136, 137, 142, 143, 144,
146, 147, 149, 153, 154, 155, 156, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 170, 171,
173, 174, 175, 176, 177, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 200, 202, 203, 204,
206, 208, 209, 210, 212, 213, 217, 220, 221, 222,
223, 227, 228, 229, 230, 234, 235, 236, 239, 240,
241, 242, 247, 248, 249, 250, 252, 253, 254, 255,
258, 259, 260, 261, 262, 264, 265, 266, 267, 268,
269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
289, 290, 291, 292, 293, 294, 295, 296, 297, 299,
300, 301, 302, 303, 304, 305, 310, 311
};


В начало OnGameModeInit

//Зарегистрируем в памяти 3 новых фильтра
CreateNewSelectorFilter(0, "Все скины", all_skins);
CreateNewSelectorFilter(1, "Женские скины", female_skin);
CreateNewSelectorFilter(2, "Мужские скины", male_skin);

//И установим фильтр со всеми скинами как фильтр по умолчанию
SetDefaultSelectorFilter_Name("Все скины");

Новый коллбэк


public OnPlayerSelectedSkin(playerid, classid)
{
//Добавляем функции-обработчики для каждого из фильтров
CallSelectorFilterByName("Все скины", all_skins);
CallSelectorFilterByName("Женские скины", female_skin);
CallSelectorFilterByName("Мужские скины", male_skin);
return 1;
}

И простая команда для переключения (вводить прямо при выборе скина)

public OnPlayerCommandText(playerid, cmdtext[])
{
if (strcmp("/s", cmdtext, true, 10) == 0)
{
switch(GetSelectorFilterForPlayer(playerid))// Узнаём текущий ID фильтра
{
case 0:// Если он равен нулю (все скины)
{// Переключаем на следующий (женские скины)
SendClientMessage(playerid, -1, "Показаны женские скины");
SetSelectorFilterForPlayer_Name(playerid, "Женские скины", female_skin);
/*
Равносильно:
SetSelectorFilterForPlayer_ID(playerid, 1, female_skin);
*/
}
case 1:// Если он равен одному (женские скины)
{// Переключаем на следующий (мужские скины)
SendClientMessage(playerid, -1, "Показаны мужские скины");
SetSelectorFilterForPlayer_Name(playerid, "Мужские скины", male_skin);
/*
Равносильно:
SetSelectorFilterForPlayer_ID(playerid, 2, male_skin);
*/
}
case 2:// Если он равен двум (мужские скины)
{// Переключаем на самый первый (все скины)
SendClientMessage(playerid, -1, "Показаны все скины");
SetSelectorFilterForPlayer_Name(playerid, "Все скины", all_skins);
/*
Равносильно:
SetSelectorFilterForPlayer_ID(playerid, 0, all_skins);
*/
}
}
return 1;
}
return 0;
}



Скины, опять же, разделим на мужские и женские (чисто для наглядности того, как нужно менять фильтры)

new police_male_skins[] =
{
265, 266, 267,
280, 281, 282,
283, 284, 300,
301, 302, 310,
311
};
//Судя по такой разнице в количестве скинов,
//Куй немножко сексист :3
new police_female_skins[] =
{
306, 307, 309
};



OnGameModeInit

CreateNewSelectorFilter(0, "Все скины", all_skins);
CreateNewSelectorFilter(1, "Женские скины", female_skin);
CreateNewSelectorFilter(2, "Мужские скины", male_skin);
SetDefaultSelectorFilter_Name("Все скины");

//К нашим старым фильтрам добавим ещё 2 новых
CreateNewSelectorFilter(3, "Женские скины (полиция)", police_female_skins);
CreateNewSelectorFilter(4, "Мужские скины (полиция)", police_male_skins);


Новый коллбэк

public OnPlayerSelectedSkin(playerid, classid)
{
CallSelectorFilterByName("Все скины", all_skins);
CallSelectorFilterByName("Женские скины", female_skins);
CallSelectorFilterByName("Мужские скины", male_skins);

//И тут парочку
CallSelectorFilterByName("Женские скины (полиция)", police_female_skins);
CallSelectorFilterByName("Мужские скины (полиция)", police_male_skins);
return 1;
}



if(!strcmp("/force", cmdtext, true))
{
//Установим игроку нужный фильтр
SetSelectorFilterForPlayer_Name(playerid, "Женские скины (полиция)", police_female_skins);
//И отправим выбирать скин
ForceClassSelection(playerid);
TogglePlayerSpectating(playerid, true);
TogglePlayerSpectating(playerid, false);
return 1;
}

//А это команда, с помощью которой будем менять фильтр
else if(!strcmp("/forcefilters", cmdtext, true, 12))
{
if(!strlen(cmdtext[14]))
return SendClientMessage(playerid, -1, "/forcefilters <м/ж>");

if(!strcmp(cmdtext[14], "м", true))//Если игрок ввёл "/forcefilters м"
{
SendClientMessage(playerid, -1, "Показаны мужские скины");
//Покажем мужские скины
SetSelectorFilterForPlayer_Name(playerid, "Мужские скины (полиция)", police_male_skins);
}
else if(!strcmp(cmdtext[14], "ж", true))//Если "ж"
{
SendClientMessage(playerid, -1, "Показаны женские скины");
//Покажем женские скины
SetSelectorFilterForPlayer_Name(playerid, "Женские скины (полиция)", police_female_skins);
}
else
SendClientMessage(playerid, -1, "/forcefilters <м/ж>");
return 1;
}


Обе системы очень примитивны и просто являются примером использования данного инклуда.
Смену фильтров Вы можете реализовать как вашей душе угодно (на видео, что я давал в самом начале статьи, смена фильтров реализована через текстдравы).
Основная задача данного инклуда - предоставить функционал. А уже как Вы им распорядитесь - ваше право :)

P.S. С данным инклудом довольно легко реализовать, например, магазин одежды. Или же систему гардероба. Да много чего можно сделать. Точнее, всё, что связано со скинами :D
Есть один маленький совет: вместо обычных ID использовать либо макросы, либо enum. Тогда проще будет контролировать свободные/занятые ID



Автор инклуда - DeimoS
Ссылка на Pastebin - Клик (http://pastebin.com/1cgndJF8)

Geebrox
09.10.2016, 01:12
Отличная работа. Очень удобная+простая с многими функционалами :good2:

$continue$
09.10.2016, 01:25
Забыл PHP тэги.
http://i.imgur.com/w3KuT80.png
И видео не работает (битая ссылка?)
http://i.imgur.com/WkbUQrp.png
И ещё массив со всеми скинами можно было бы заполнить при запуске мода (чтобы не вписывать в ручную каждый скин, только пропустить итерацию 74 и код стал бы намного красивей, но ты проделал лишнею работу)

DeimoS
09.10.2016, 01:57
И видео не работает (битая ссылка?)

Битый аккаунт
http://i.imgur.com/b8K3rcX.png


И ещё массив со всеми скинами можно было бы заполнить при запуске мода (чтобы не вписывать в ручную каждый скин, только пропустить итерацию 74 и код стал бы намного красивей, но ты проделал лишнею работу)
Эмм, а кто сказал, что я его вручную заполнял? :fool:
Если ты имеешь ввиду заполнение циклом, а не "визуальное" заполнение, то тут всё упирается в функциональность. В массиве я могу, например, выставить скины в нужном мне порядке, перемешивая их как угодно. Могу убрать какие-то скины. Да много чего могу. С циклом же такое не провернуть так же легко, как с массивом.

А 74-ый скин оставлен для того, чтоб не забыть о нём в случае чего.