Правила форума Гаранты форума
Размещение рекламы AMX-X компилятор

Здравствуйте, гость Вход | Регистрация

Наши новости:

14-дек
24-апр
10-апр
11-апр

Плагин "Spring" // Rus: "Пружина" (v2.0.1)

, Плагин дает возможность создавать пружины на карте через удобное меню.
Статус пользователя wellasg00d
сообщение 13.10.2019, 18:13
Сообщение #1


Стаж: 10 лет
Город: Москва

Сообщений: 3
Благодарностей: 8
Полезность: 0

Плагин - "Spring" // Rus: "Пружина"

Прикрепленное изображение

Подробная информация:

Описание:
Описание: Дает возможность создавать пружины на карте через удобное меню. Гибкая настройка плагина, позволит сделать все так, как Вам нужно на Вашем сервере в зависимости от мода.


Автор:
wellasgood



Совместимость:
Amx Mod X 1.9.0, Amx Mod X 1.10.0 dev


Что умеет (процесс начальной разработки):

- Создание начальных основ, продумка идеи и тп.​
- Реализовано создание необходимых директорий и файлов. (которые неообходимы по замыслу плагина)​
- Реализован функционал задействования клавишей клавиатуры прыжка на пружине​
- Реализован функционал феерверка (гибкая настройка) при прыжке (вкл/выкл)​
- Сбор и подготовка необходимых Stock функций (в конце кода) для функционирования всего.​
- Реализована настройка плагина в конфиге. (spring/spring.cfg)​
- Возможность сохранения расставленных пружин через меню, для последующего воспроизведения на каждой отдельной карте какой хотите.​
- Добавлена слышимость производимых звуков для Steam и Non-Steam игроков.​
- Разработана с нуля модель пружинного борда.​
- Реализована функция расставления сохраненных моделей на карте при запуске карты. (запуске сервера, перезапуске, смены карты; :D)​
- Реализовано удобное меню создания пружины на карте, с доп. возможностями.​
- Реализовано меню перемещения пружины после создания (через доп. меню)​
- Добавлена функция свечения модели (яркость свечения оболчки модели)​
- Сделана продуманная выдача бессмертия после прыжка на пружине (дабы после прыжка когда игрок падает не тратилось здоровье)​
- Реализовано удаление как 1 пружины при наведении, так и всех расставленных сразу на карте.​
- Добавлена возможноть разрешить использовать пружину только админам или мульти-флаг игрокам.​
- Оптимизация кода и небольшие поправки в части разных функций.​
- Все сообщения выведены в LANG файл.​
- Проверка на работоспособность в игре == успешно.​

* - Информация о других версиях и доработках (в спойлере: 'Обновления').​


Мультиязычность:
RU, EN


Требования:
ReSemiclip (желательно) или ReGameDLL (mp_kill_filled_spawn), иначе Unstuck или Stuck RBS, для мода с клеткой.


Благодарности:
voed, d3m37r4, fantom, Denzer, WILL_BE, fl0wer, w0w, Jumper, Mistrick, BlackSignature, quasar



Скриншоты (мод: 'Пружина-Борд'):


Версия модели #1:

Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение


Версия модели #2:

Прикрепленное изображение
Прикрепленное изображение




Скриншоты (пружина-клетка):

Прикрепленное изображение



Команды:

Открытие главного меню: /sp-menu
Команды для игроков: /freedom, /pardon


Установка:

Скомпилируйте плагин.
Скопируйте скомпилированный файл .amxx в директорию: amxmodx/plugins/
Пропишите .amxx в файле amxmodx/configs/plugins.ini
Скопируйте словарь плагина .txt в директорию amxmodx/data/lang/
Скопируйте конфиг плагина .cfg в директорию amxmodx/configs/spring/
Скопируйте файлы .mdl в директорию models/spring/
Скопируйте файлы .wav в директорию sound/spring/
Скопируйте файлы .spr в директорию sprites/spring/
Смените карту или перезапустите сервер.


Настройки:


В .sma:

Код:
#define SPRING_NEW_MODEL //(откомментировать если используется новая модель пружинного борда)
new const ACCESS_MENU_FLAG = ADMIN_CFG; //для доступа (главное меню, создание и тп)
new const ACCESS_ADMIN_FLAG = ADMIN_BAN; //если использование прыжка только для админов (также фигурирует в доступе к главному меню, перемещение для админов)
new const ACCESS_VIP_FLAG = ADMIN_LEVEL_H; //для подстановки в коде! (флаг который есть у випов на вашем сервере!)
new const ACCESS_MULTI_FLAG = (ADMIN_BAN|ADMIN_LEVEL_H); //мульти флаг (на данном примере будет разрешено использование только админам и вип)
new const ACCESS_CAGE_FLAG = ADMIN_IMMUNITY; //флаг для иммунитета от перемещения в клетку. (игрок будет прозрачным от нажатия в меню)



В .cfg:

Код
/*--- НАСТРОЙКИ ПЛАГИНА ПРУЖИНЫ ---*/


//Настройка возможности использования пружины для отдельных категорий:

sp_access_en "2" //Всем/Админы/Мульти-Флаг - 0/1/2 кому можно использовать.


//Настройка сброса бессмертия для прыгающего игрока. (зависит от длинны прыжка вверх, т.е чем дальше прыжок вверх (значения sp_jmspeed_min(max)), тем больше нужно выставлять время.

sp_time_offdmg "5.0" //время до отключения бессмертия (бессмертие действует только для victim, т.е для игрока который прыгает. Другие смогут его убить.) fmt Float.


//Настройка прыжка (для подстановки в рандом функцию, т.е дальность отскока от пружины вверх, будет рандомным числом между минимальным и максимальным значением):

sp_jmspeed_min "400.0" //Мин. скорость прыжка вверх (отскок от пружины) fmt Float.

sp_jmspeed_max "600.0" //Макс. скорость прыжка вверх (отскок от пружины) fmt Float.


//Настройка свечения модели пружины (оболочка):

sp_render_amount "80" //Яркость свечения оболочки модели


//Настройка функций феерверка при прыжке:

sp_firework_en "1" //Вкл/Выкл - 1/0 запуск феерверка при прыжке.

sp_firework_num "3" //Кол-во раз подряд запуска феерверка при прыжке.

sp_firework_time1 "0.3" //время до запуска первого феерверка. fmt Float.

sp_firework_time2 "0.8" //время до повторного заряда феерверка fmt Float.

sp_firework_msg "1" //Одному/Всем - 1/0 видимость феерверка около игрока.


//Настройка слышимости музыки плагина:

sp_sound_check "1" //Всем/Одному - 0/1 кому слышна музыка.


//ОТДЕЛЬНЫЙ МОД 'КЛЕТКА' НАСТРОЙКИ:

sp_сage_offdmg "1" //Убивать в клетке между Т и КТ? (0/1 - выкл/вкл) в клетке

spcage_jmspeed_min "400.0" //Мин. скорость прыжка вверх fmt Float. в клетке

spcage_jmspeed_max "600.0" //Макс. скорость прыжка вверх fmt Float. в клетке

sp_cagetime_en "1" //Вкл/Выкл - 1/0 возможность сажать в клетку на время.

sp_cagetime_1 "3" //Время на которое сажать игрока в клетку (мин).

sp_cagetime_2 "7" //Время на которое сажать игрока в клетку (мин).

sp_cagetime_3 "10" //Время на которое сажать игрока в клетку (мин).

sp_cagetime_4 "15" //Время на которое сажать игрока в клетку (мин).

sp_cagetime_5 "20" //Время на которое сажать игрока в клетку (мин).

sp_cagekill_en "1" //Вкл/Выкл - 1/0 убивать игрока(ов) в клетке через время (дабы избежать такого, что в клетке кто-то есть, а раунд все идет и подобных случаев)

sp_cagekill_time "5.0" //через сколько сек убивать игрока(ов) в клетке

sp_cagekill_info "1" //Вкл/Выкл - 1/0 инфо игрокам в клетке, сколько им осталось до смерти


//Перемещение объектов

sp_move_cvar "10.0" //значение для функции перемещения (подстановка в коде, дальность, чем больше значение, тем быстрее Вы передвинете объект)

echo "Spring plugin configuration completed successfully!"





Исходный код:

Код:
/*
* - ----------
Плагин - "Spring" // Rus: "Пружина"
* - ----------
Описание - Суть плагина в том, что можно расставлять по карте пружины, на которых можно прыгать игрокам.
* - ----------
Благодарность за помощь (содействие): - voed, d3m37r4, fantom, Denzer, WILL_BE, fl0wer, Jumper, w0w, Mistrick, BlackSignature
* - ----------
Благодарность за перевод на разные языки: wellasgood
* - ----------
Поддержка плагина:
* - ----------
Dev-Cs: @wellasgood
vk: https://vk.com/d1mkin
Telegram: @WellAsGood
* - ----------
* - ----------
* - Версии:
* - ----------
* - ----------
* - ver 1.0:
- Создание начальных основ, продумка идеи и тп.
- Реализовано создание необходимых директорий и файлов. (которые неообходимы по замыслу плагина)
- Реализован функционал задействования клавишей клавиатуры прыжка на пружине
- Реализован функционал феерверка (гибкая настройка) при прыжке (вкл/выкл)
- Сбор и подготовка необходимых Stock функций (в конце кода) для функционирования всего.
- Реализована настройка плагина в конфиге. (spring/spring.cfg)
- Возможность сохранения расставленных пружин через меню, для последующего воспроизведения на каждой отдельной карте какой хотите.
- Добавлена слышимость производимых звуков для Steam и Non-Steam игроков.
- Разработана с нуля модель пружинного борда.
- Реализована функция расставления сохраненных моделей на карте при запуске карты. (запуске сервера, перезапуске, смены карты; :D)
- Реализовано удобное меню создания пружины на карте, с доп. возможностями.
- Реализовано меню перемещения пружины после создания (через доп. меню)
- Добавлена функция свечения модели (яркость свечения оболчки модели)
- Сделана продуманная выдача бессмертия после прыжка на пружине (дабы после прыжка когда игрок падает не тратилось здоровье)
- Реализовано удаление как 1 пружины при наведении, так и всех расставленных сразу на карте.
- Добавлена возможноть разрешить использовать пружину только админам или мульти-флаг игрокам.
- Оптимизация кода и небольшие поправки в части разных функций.
- Все сообщения выведены в LANG файл.
- Проверка на работоспособность в игре == успешно.
* - ver 1.1:
- Правка кода функции феерверка (был обнаружен потанциальный краш), cпасибо: voed
- Небольшая правка кода (изменил расположение g_UserFlags, удалил return FMRES_IGNORED; где вывод сообщений), спасибо: d3m37r4, fantom
- Изменено бессмертие (fm_set_user_godmode) на отлов события (Ham_TakeDamage), дабы в полете урон можно было наносить другим игрокам, спасибо: Denzer, WILL_BE
- Реализовано мультиязычное меню (теперь пункты меню в LANG файле)
- Из внутриностей менюшек убраны не нужные значения, которые лишь захломляли код, спасибо: fl0wer
- Из кода убраны переменные и значения которые больше не нужны, а также добавлено нужное новое.
- Добавлен квар (sp_time_offdmg). время до отключения бессмертия (бессмертие действует только для victim, т.е для игрока который прыгает. Другие смогут его убить.)
* - ver 1.2:
- Функция SendAudio заменена на Emit_Sound, что бы звук не распростронялся на всю карту, спасибо: Jumper, w0w
- Добавлен новый квар (SPRING_SOUND_CHECK) == выбор между слышимостью всем или 1 игроку который использует звук. (0/1 - всем/одному; настройка в .cfg), спасибо: Jumper
- Добавлено уничтожение меню после его использования (menu_destroy), дабы не утекала память (могло привести к лагам на сервере и тп), спасибо: Mistrick
- Критичное обновление (рекомендация обновиться, так как, обновление касающееся утечки памяти не стоит игнорировать.)
* - ver 1.3:
- Исправлен код в части выдачи прыжка совместно с fw_TakeDamage, конкретно переменная g_NoDamage сделана массивом, так как, если несколько прыгают на пружине сразу, все бы ломалось, спасибо: Denzer, Mistrick
- Добавлено уничтожение менюшек в еще несколько частей кода (menu_destroy(menu);), дабы не утекала память!, спасибо: Mistrick
- Опять же, обновление критично из-за утечки памяти (возможны лаги на предыдущих версиях), обязательно к обновлению!
* - ver 1.4:
- Добавлен отдельная система этого плагина, под названием: 'Spring Cage'; Rus: 'Пружинная клетка':
- Для чего и как работает: После создания клетки-пружины на карте, можно поместить любого игрока через доп. меню выбора. (это может быть наказание или еще что-то; флуд, спам, подумать над поведением).
- Добавлена возможность разместить игрока в клетку на время (выбирается в меню), если игрок находится в клетке, и настанет новый раунд, он всеравно окажется там же, если его время выхода еще непришло!
- Созданы необходимые квары, функции, меню и тп.
- Оптимизация кода по замечаниям.
- Создано меню телепорта игрока в клетку.
- Внедрена система времени на которое перемещается игрок в клетку
- Добавлена команда для чата /freedom, узнать сколько времени перемещенному в клетку осталось там сидеть.
- Добавлены новые переменные, счетчики + массивы и переключатели bool, для разных функций связанных с клеткой. (гибче настройка под Ваши нужды)
- Добавлено: Игрок из клетки может попросить прощения у присутствующих админов на сервере, админам придет уведомление, что игрок в клетке.
- Добавлено: Меню для досрочного освобождения из клетки (для админов)
- Реализовано сохранение тех игроков, которые хотят обойти клетку. (т.е при выходе инфа сохраняется, и при входе такого игрока он опять окажется в клетке), спасибо: BlackSignature
- Правки в коде с учетом новых переменных. (+ оптимизация)
- Все логи теперь выводятся в отдельный файл. (logs/spring/)
* - ver 1.5:
- В ходе длительной проверки на сервере с реальными игроками, были обнаружены баги.
- Правки в коде (часть игнора игроков в меню перемещения и освобождения; get_user_flags(id) заменено на get_user_flags(iPlayer)), игнорились все (из-за id)
- Правки в коде (часть события spawn, добавлена проверка поиска по классу, так как игроки не телепортировались в новом раунде в клетку!)
- Критическое обновление!
* - ver 1.5:
- В ходе длительной проверки на сервере с реальными игроками, были обнаружены баги.
- Правки в коде (часть игнора игроков в меню перемещения и освобождения; get_user_flags(id) заменено на get_user_flags(iPlayer)), игнорились все (из-за id)
- Правки в коде (часть события spawn, добавлена проверка поиска по классу, так как игроки не телепортировались в новом раунде в клетку!)
- Критическое обновление!
* - ver 1.6:
- Оптимизирован код, улучшена читабельность.
- Подправлены комментарии или в некоторых местах где и так все понятно убраны вообще.
- Исправлено вызов меню из другого меню (когда освобождаешь игрока из клетки (меню освобождение), то после вызывалось меню телепортации в клетку).
- Убраны большое кол-во stock в пользу public, остались только необходимые stock.
- Убран из события SPAWN, цикл и функция user_slap (вместо этого добавлены в описание плагина необходимые требования для использования (желательно))
- Убраны лишнии строки в различных случаях где это можно сделать, дабы уменьшить код.
- Требования: ReSemiclip (желательно) или ReGameDLL (mp_kill_filled_spawn), иначе Unstuck или Stuck RBS (выталкивание игрока из игрока)
* - ver 1.7:
- Оптимизирован код в части циклов while, подправлены скобки, освобождение места в пользу меньших строк кода.
* - ver 1.8:
- Исправлена утечка в меню (!is_user_connected) перемещено в другое место во всех меню.
- В событии Ham_TakeDamage, далее выполняемой функции > 'fw_TakeDamage' изменена проверка, убрано (!is_user_connected) и оставлено только (is_user_alive), так как (is_user_alive), проверяет сначала подключен ли игрок.
* - ver 1.9:
- Реализована возможность убивать игрока(ов) в клетке через заданное время (дабы избежать простаивания раунда, если все игроки за клеткой мертвы и подобных случаев)
- Добавлены новые переменные, квары, функции.
- Сделано событие смерти игрокаов в клетке без сообщения в верхнем правом углу, т.е игроки в клетке будут незаметно убиты, будто их и нет в игре (не мешают игровому процессу остальным).
- Реализовано эффектная смерть в клетке игрока.
- Добавлена const переменная (флаг иммунитета от попадания в клетку)
- Добавлены новые сообщения в LANG файл.
- Добавлены новые квары в CFG файл.
* - ver 2.0:
- Добавлены новый квар, который устанавливает на сколько по дальности перемещать объекты по координатам.
- Вывод логов сделаны мультиязычными (спасибо: ребятам с форума Dev-Cs (w0w, the_hunter) за пояснения).
- Были внесены изменения в LANG файл.
- Были внесены изменения в CFG файл.
* - ver 2.0.1:
- Добавлены новый #define SPRING_NEW_MODEL (если закомментирован, то используется старая модель пружинного борда, если откомментировано, то используется новая модель)
- Переход на трех значную систему версий. =)
* - ----------
* - ----------
* - Актуальная версия плагина (конечная с учетом переделок: ver 2.0.1)
* - ----------
*/

#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <hamsandwich>
#include <xs>
#include <engine>

#if !defined MAX_MAPNAME_LENGTH
#define MAX_MAPNAME_LENGTH 64
#endif

//#define SPRING_NEW_MODEL //(откомментировать если используется новая модель пружинного борда)

//Необходимые сonst для разных предназначений
new const PLUGIN[] = "Spring";
new const VERSION[] = "2.0.1";
new const AUTHOR[] = "wellasgood";

new const ACCESS_MENU_FLAG = ADMIN_CFG; //для доступа (главное меню, создание и тп)
new const ACCESS_ADMIN_FLAG = ADMIN_BAN; //если использование прыжка только для админов (также фигурирует в доступе к главному меню, перемещение для админов)
new const ACCESS_VIP_FLAG = ADMIN_LEVEL_H; //для подстановки в коде! (флаг который есть у випов на вашем сервере!)
new const ACCESS_MULTI_FLAG = (ADMIN_BAN|ADMIN_LEVEL_H); //мульти флаг (на данном примере будет разрешено использование только админам и вип)
new const ACCESS_CAGE_FLAG = ADMIN_IMMUNITY; //флаг для иммунитета от перемещения в клетку. (игрок будет прозрачным от нажатия в меню)

new const SPRING_SND[] = "spring/spring.wav";

#if !defined SPRING_NEW_MODEL
new const SPRING_MDL[] = "models/spring/spring.mdl";
#else
new const SPRING_MDL[] = "models/spring/spring-new.mdl";
#endif

new const SPRING_CAGE1_MDL[] = "models/spring/Cage_1.mdl";
new const SPRING_CAGE2_MDL[] = "models/spring/Cage_2.mdl";
new const SPRING_CAGE3_MDL[] = "models/spring/Cage_3.mdl";
new const SPRING_CAGE4_MDL[] = "models/spring/Cage_4.mdl";
new const SPRING_CAGE5_MDL[] = "models/spring/Cage_5.mdl";

new const SPRING_DIR[] = "spring";
new const SPRING_SAVE[] = "spring_save";
new const SPRING_LOG_DIR[] = "logs/spring";
new const SPRING_CFG[] = {"addons/amxmodx/configs/spring/spring.cfg"};

new const Float:SPRING_MIN[3] = {-14.86, 0.00, -35.88}; //Размеры для пружины (была произведена колибровка)
new const Float:SPRING_MAX[3] = {14.86, 14.83, 35.88}; //Размеры для пружины (была произведена колибровка)
new const Float:SPRING_CAGE1_MIN[3] = {-76.06, -50.92, -76.17}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE1_MAX[3] = {-74.27, 50.42, 400.92}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE2_MIN[3] = {-76.06, -60.00, -76.17}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE2_MAX[3] = {76.27, -58.42, 400.92}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE3_MIN[3] = {-76.06, 35.92, -76.17}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE3_MAX[3] = {76.27, 36.42, 400.92}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE4_MIN[3] = {76.06, -50.92, -76.17}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE4_MAX[3] = {77.27, 50.42, 400.92}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE5_MIN[3] = {-76.06, -58.92, -76.17}; //Размеры для части пружины-клетки (была произведена колибровка)
new const Float:SPRING_CAGE5_MAX[3] = {76.27, 35.28, 5.27}; //Размеры для части пружины-клетки (была произведена колибровка)

//Необходимые переменные, счетчики, массивы и др.:
new SPRING_BUTTON, SPRING_JUMPSPEED_MIN, SPRING_JUMPSPEED_MAX, SPRING_RENDER_AMOUNT, SPRING_TIME_OFFDAMAGE, SPRING_SOUND_CHECK, SPRING_ACCESS_EN;
new SPRING_FIREWORK_EN, SPRING_FIREWORK_NUM, SPRING_FIREWORK_MSG, SPRING_FIREWORK_TIME1, SPRING_FIREWORK_TIME2;
new SPRING_CAGETIME_EN, SPRING_CAGETIME_1, SPRING_CAGETIME_2, SPRING_CAGETIME_3, SPRING_CAGETIME_4, SPRING_CAGETIME_5;
new SPRINGCAGE_OFFDAMAGE, SPRINGCAGE_JUMPSPEED_MIN, SPRINGCAGE_JUMPSPEED_MAX, SPRING_CAGEKILL_EN, SPRING_CAGEKILL_TIME, SPRING_CAGEKILL_INFO, SPRING_MOVE_CVAR;

new g_NoDamage[MAX_PLAYERS+1], g_FireworkCount, g_SpringEnt, g_szLogPath[64];
new bool:g_Player[MAX_PLAYERS+1], g_Time[MAX_PLAYERS+1], g_CheckPlayer;
new Float:g_pOrigin[MAX_PLAYERS+1][3];
new Trie:g_tTrie;

new g_shortSpr[6];
new g_short[6][] =
{
"sprites/spring/3dmflared.spr",
"sprites/spring/3dmflaora.spr" ,
"sprites/spring/frostgib.spr" ,
"sprites/spring/ledglow.spr" ,
"sprites/spring/pink.spr" ,
"sprites/spring/star_gib.spr"
};

public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR);

// Отключаем не нужные карты (на картах, начинающихся на эти префиксы, не будет работать плагин (если не нужно, то '//' строки))
new mapname[MAX_MAPNAME_LENGTH];
get_mapname(mapname, charsmax(mapname));
new maps[][] = { "$", "fy_", "aim_" };
for(new i; i < sizeof maps; i++){
if(containi(mapname, maps[i]) != -1){
pause("ad");
return;
}
}

register_dictionary("spring.txt");

RegisterHam(Ham_Use, "func_button", "fwdUse", 0);
RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage", 0);
RegisterHamPlayer(Ham_Spawn, "fw_SpawnPlayer", 1);

register_clcmd("say /sp-menu", "cmdSpringMenu");
register_clcmd("say /freedom", "cmdFreedom");
register_clcmd("say /pardon", "cmdPardon");

g_tTrie = TrieCreate()
SPRING_BUTTON = engfunc(EngFunc_AllocString, "func_button");

SPRING_ACCESS_EN = create_cvar("sp_access_en", "1", FCVAR_NONE, "Access spring use", true, 0.0, true, 2.0); //Всем/Админы/Мульти-Флаг - 0/1/2 кому можно использовать.
SPRING_TIME_OFFDAMAGE = create_cvar("sp_time_offdmg", "5.0", FCVAR_NONE, "Spring time damage off", true, 0.0, true, 32.0); //Время до сброса бессмертия fmt Float.
SPRINGCAGE_OFFDAMAGE = create_cvar("sp_сage_offdmg", "0", FCVAR_NONE, "Spring cage damage off or on", true, 0.0, true, 1.0); //Убивать в клетке между Т и КТ? (0/1 - выкл/вкл)
SPRING_JUMPSPEED_MIN = create_cvar("sp_jmspeed_min", "400.0", FCVAR_NONE, "Jump speed min", false, 0.0, false, 0.0); //Мин. скорость прыжка вверх (отскок) fmt Float.
SPRING_JUMPSPEED_MAX = create_cvar("sp_jmspeed_max", "700.0", FCVAR_NONE, "Jump speed max", false, 0.0, false, 0.0); //Макс. скорость прыжка вверх (отскок) fmt Float.
SPRINGCAGE_JUMPSPEED_MIN = create_cvar("spcage_jmspeed_min", "200.0", FCVAR_NONE, "Jump speed min cage", false, 0.0, false, 0.0); //Мин. скорость прыжка вверх fmt Float.
SPRINGCAGE_JUMPSPEED_MAX = create_cvar("spcage_jmspeed_max", "400.0", FCVAR_NONE, "Jump speed max cage", false, 0.0, false, 0.0); //Макс. скорость прыжка вверх fmt Float.
SPRING_RENDER_AMOUNT = create_cvar("sp_render_amount", "70", FCVAR_NONE, "Render amount model", false, 0.0, false, 0.0); //Яркость свечения оболочки модели (только борд)
SPRING_FIREWORK_EN = create_cvar("sp_firework_en", "1", FCVAR_NONE, "Firework enabled spring board", true, 0.0, true, 1.0); //Вкл/Выкл - 1/0 запуск феерверка при прыжке на борде.
SPRING_FIREWORK_NUM = create_cvar("sp_firework_num", "1", FCVAR_NONE, "Firework count", false, 0.0, false, 0.0); //Кол-во раз подряд запуска феерверка при прыжке.
SPRING_FIREWORK_TIME1 = create_cvar("sp_firework_time1", "0.3", FCVAR_NONE, "Time Fw Hud", true, 0.0, true, 32.0); //время до запуска первого феерверка. fmt Float.
SPRING_FIREWORK_TIME2 = create_cvar("sp_firework_time2", "0.8", FCVAR_NONE, "Time Fw Hud", true, 0.0, true, 32.0); //время до повторного заряда феерверка fmt Float.
SPRING_FIREWORK_MSG = create_cvar("sp_firework_msg", "1", FCVAR_NONE, "Firework Message", true, 0.0, true, 1.0); //Одному/Всем - 1/0 видимость феерверка около игрока.
SPRING_SOUND_CHECK = create_cvar("sp_sound_check", "1", FCVAR_NONE, "Spring sound check", true, 0.0, true, 1.0); //Всем/Одному - 0/1 кому слышна музыка.
SPRING_CAGETIME_EN = create_cvar("sp_cagetime_en", "1", FCVAR_NONE, "Spring cage time enabled", true, 0.0, true, 1.0); //Вкл/Выкл - 1/0 возможность сажать в клетку на время.
SPRING_CAGETIME_1 = create_cvar("sp_cagetime_1", "10", FCVAR_NONE, "Spring cage time 1", false, 0.0, false, 0.0); //Время на которое сажать игрока в клетку (мин).
SPRING_CAGETIME_2 = create_cvar("sp_cagetime_2", "15", FCVAR_NONE, "Spring cage time 2", false, 0.0, false, 0.0); //Время на которое сажать игрока в клетку (мин).
SPRING_CAGETIME_3 = create_cvar("sp_cagetime_3", "20", FCVAR_NONE, "Spring cage time 3", false, 0.0, false, 0.0); //Время на которое сажать игрока в клетку (мин).
SPRING_CAGETIME_4 = create_cvar("sp_cagetime_4", "25", FCVAR_NONE, "Spring cage time 4", false, 0.0, false, 0.0); //Время на которое сажать игрока в клетку (мин).
SPRING_CAGETIME_5 = create_cvar("sp_cagetime_5", "30", FCVAR_NONE, "Spring cage time 5", false, 0.0, false, 0.0); //Время на которое сажать игрока в клетку (мин).
SPRING_CAGEKILL_EN = create_cvar("sp_cagekill_en", "1", FCVAR_NONE, "Spring cage kill player(s)", true, 0.0, true, 1.0); //Вкл/Выкл - 1/0 убивать игрока(ов) в клетке через время
SPRING_CAGEKILL_TIME = create_cvar("sp_cagekill_time", "60.0", FCVAR_NONE, "Spring cage kill time", false, 0.0, false, 0.0); //через сколько сек убивать игрока(ов) в клетке
SPRING_CAGEKILL_INFO = create_cvar("sp_cagekill_info", "1", FCVAR_NONE, "Spring cage kill info)", true, 0.0, true, 1.0); //Вкл/Выкл - 1/0 инфо за 5 сек до смерти игрока в клетке
SPRING_MOVE_CVAR = create_cvar("sp_move_cvar", "10.0", FCVAR_NONE, "Spring move cvar", false, 0.0, false, 0.0); //значение для функции перемещения (подстановка в коде, дальность)
}

public plugin_cfg()
{
new paths[64], otherspaths[100];
spring_get_configsdir(paths, 63);

if(!dir_exists(paths)){
mkdir(paths);
}

formatex(otherspaths, 99, "%s/%s", paths, SPRING_SAVE);

if(!dir_exists(otherspaths)){
mkdir(otherspaths);
}

if(file_exists(SPRING_CFG)){
server_cmd("exec %s", SPRING_CFG);
}

new Date[16];
get_time("%d_%m_%y", Date, charsmax(Date));

get_localinfo("amxx_basedir", g_szLogPath, charsmax(g_szLogPath));
new iLen = formatex(g_szLogPath, charsmax(g_szLogPath), "%s/%s",g_szLogPath, SPRING_LOG_DIR);

if(!dir_exists(g_szLogPath)){
mkdir(g_szLogPath);
}

formatex(g_szLogPath[iLen], charsmax(g_szLogPath) - iLen, "/spring-log_%s.txt", Date);

read_spring();
}

public plugin_precache()
{
precache_sound(SPRING_SND)

precache_model(SPRING_MDL)
precache_model(SPRING_CAGE1_MDL)
precache_model(SPRING_CAGE2_MDL)
precache_model(SPRING_CAGE3_MDL)
precache_model(SPRING_CAGE4_MDL)
precache_model(SPRING_CAGE5_MDL)

for(new i; i < sizeof g_short; i++){
g_shortSpr[i] = precache_model(g_short[i]);
}
}

public client_authorized(iPlayer, const szAuthID[]) //Получаем данные если игрок зашел
{
if(TrieGetCell(g_tTrie, szAuthID, g_Time[iPlayer])){
TrieDeleteKey(g_tTrie, szAuthID)
}
}

public client_disconnected(iPlayer) //Сохраняем данные если игрок вышел
{
if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1){
new szAuthID[MAX_AUTHID_LENGTH];

get_user_authid(iPlayer, szAuthID, charsmax(szAuthID))
TrieSetCell(g_tTrie, szAuthID, g_Time[iPlayer])

g_Time[iPlayer] = 0;
g_Player[iPlayer] = false;
}
}

public fw_SpawnPlayer(iPlayer) //Событие spawn действует для тех, у кого по условиям проходит.
{
if(!is_user_alive(iPlayer)) return HAM_IGNORED;

if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1){
if(get_pcvar_num(SPRING_CAGETIME_EN) == 1){
if(g_Time[iPlayer] < 1){
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_FREEDOM1");
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_FREEDOM2");

fm_set_user_godmode(iPlayer, 0);
g_Player[iPlayer] = false;
g_Time[iPlayer] = 0;

return HAM_IGNORED;
}
else{
new Min = g_Time[iPlayer] - time();

client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_TIMECHECK", Min / 60);
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_PARDONINFO");
}
}

//спавн в клетку
new Float:v_Origin[3], ent;

while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "T-Cage_spring"))){
pev(ent, pev_origin, v_Origin)
}

ent = 0;
v_Origin[2] += 60;

set_pev(iPlayer, pev_velocity, Float:{0.0, 0.0, 0.0})
set_pev(iPlayer, pev_origin, v_Origin)

if(get_pcvar_num(SPRINGCAGE_OFFDAMAGE) == 0){
fm_set_user_godmode(iPlayer, 1);
}

//Убиваем тех кто в клетке через время (дабы избежать такого, что в клетке кто-то есть, а раунд все идет и подобных случаев)
if(get_pcvar_num(SPRING_CAGEKILL_EN) == 1){
if(get_pcvar_num(SPRING_CAGEKILL_INFO) == 1){
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_KILLINFO", iPlayer, get_pcvar_num(SPRING_CAGEKILL_TIME));
}
remove_task(iPlayer);
set_task(get_pcvar_float(SPRING_CAGEKILL_TIME), "Spring_Cage_Kill_Eff1", iPlayer);
}

//Инфа по поводу возможности не поподать в клетку впринципе (как получить иммунитет)
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_IMMUNINFO");
}

return HAM_IGNORED;
}

public Spring_Cage_Kill_Eff1(iPlayer) //эффект при убийстве игроков в клетке / часть 1.
{
new Float:velocity1[3];

entity_get_vector(iPlayer,EV_VEC_velocity,velocity1)
velocity1[2] += 1000;
entity_set_vector(iPlayer,EV_VEC_velocity,velocity1)

set_task(0.5, "Spring_Cage_Kill_Eff2", iPlayer);
}

public Spring_Cage_Kill_Eff2(iPlayer) //эффект при убийстве игроков в клетке / часть 2.
{
new Float:velocity2[3];

entity_get_vector(iPlayer,EV_VEC_velocity,velocity2)
velocity2[2] -= 1000;
entity_set_vector(iPlayer,EV_VEC_velocity,velocity2)

set_task(1.0, "Spring_Cage_Kill_Eff3", iPlayer);
}

public Spring_Cage_Kill_Eff3(iPlayer) //эффект при убийстве игроков в клетке / часть 3.
{
new Float:velocity3[3];

entity_get_vector(iPlayer,EV_VEC_velocity,velocity3)
velocity3[2] += 1000;
entity_set_vector(iPlayer,EV_VEC_velocity,velocity3)

set_task(0.5, "Spring_Cage_Kill_Eff4", iPlayer);
}

public Spring_Cage_Kill_Eff4(iPlayer) //эффект при убийстве игроков в клетке / часть 4.
{
new Float:velocity4[3];

entity_get_vector(iPlayer,EV_VEC_velocity,velocity4)
velocity4[2] -= 1000;
entity_set_vector(iPlayer,EV_VEC_velocity,velocity4)

set_task(3.0, "Spring_Cage_Kill", iPlayer);
}

public Spring_Cage_Kill(iPlayer) //Функция смерти игроков которые в клетке / часть 5.
{
fm_set_user_godmode(iPlayer, 0); //если стояло бессмертие убираем для килла.
user_silentkill(iPlayer); //убиваем, что никто не увидет сообщения об этом, в верхнем правом углу.
}

public cmdFreedom(iPlayer) //узнать сколько осталось сидеть в клетке по команде
{
if(!is_user_alive(iPlayer)) return PLUGIN_HANDLED;

if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1){
if(get_pcvar_num(SPRING_CAGETIME_EN) == 1){
if(g_Time[iPlayer] > 1){
new Min = g_Time[iPlayer] - time();

client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_TIMECHECK", Min / 60);
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_PARDONINFO");
}
}
}

return PLUGIN_HANDLED;
}

public cmdPardon(iPlayer) //Игрок из клетки просит кого-то из админов его высунуть (прощения)
{
if(!is_user_alive(iPlayer)) return PLUGIN_HANDLED;

if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1){
new iPlayersID[MAX_PLAYERS], iPlayerNum, iCheckAdmin;
get_players_ex(iPlayersID, iPlayerNum, GetPlayers_ExcludeDead|GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV);

for(new i; i < iPlayerNum; i++){
if(get_user_flags(iPlayersID[i]) & ACCESS_ADMIN_FLAG){
client_print_color(iPlayersID[i], print_team_default, "%l", "SPRING_CAGE_PARDON1", iPlayersID[i], iPlayer);
client_print_color(iPlayersID[i], print_team_default, "%l", "SPRING_CAGE_PARDON2");

iCheckAdmin = 1;
}
}

if(iCheckAdmin == 1){
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_PARDON3", iPlayer);
iCheckAdmin = 0;
}
else{
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_PARDON4", iPlayer);
}

log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG1", iPlayer);
}

return PLUGIN_HANDLED;
}

public read_spring() //Расстановка уже сохраненных точек на карте.
{
new mapname[MAX_MAPNAME_LENGTH], springfile[128];
get_mapname(mapname, MAX_MAPNAME_LENGTH-1);

spring_get_configsdir(springfile, 127);
formatex(springfile, 127, "%s/%s/%s.cfg", springfile, SPRING_SAVE, mapname);

if(!file_exists(springfile)){
return;
}

new szData[41];
new szType[1], szX[13], szY[13], szZ[13];
new Float:vOrigin[3];
new f = fopen(springfile, "rt");

while(!feof(f)){
fgets(f, szData, 40)
parse(szData, szType, 1, szX, 12, szY, 12, szZ, 12)

vOrigin[0] = str_to_float(szX)
vOrigin[1] = str_to_float(szY)
vOrigin[2] = str_to_float(szZ)

if(szType[0] == 'S'){
makeBox(0, 1, "Spring", vOrigin)
}
else if(szType[0] == 'Q'){
makeBox(0, 2, "Q-Cage_spring", vOrigin)
}
else if(szType[0] == 'W'){
makeBox(0, 3, "W-Cage_spring", vOrigin)
}
else if(szType[0] == 'E'){
makeBox(0, 4, "E-Cage_spring", vOrigin)
}
else if(szType[0] == 'R'){
makeBox(0, 5, "R-Cage_spring", vOrigin)
}
else if(szType[0] == 'T'){
makeBox(0, 6, "T-Cage_spring", vOrigin)
}
else{
log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG2", springfile);
fclose(f);
return;
}
}

fclose(f);
log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG3", springfile);
}

public fwdUse(ent, id) //Отлов события нажатия клавиши "E" на клавиатуре в игре, ('E' == use)
{
if(!ent || id > 32){
return FMRES_IGNORED;
}

if(!is_user_alive(id)){
return FMRES_IGNORED;
}

//Настройка использования (кому можно использовать):
new g_UserFlags = get_user_flags(id);

if(get_pcvar_num(SPRING_ACCESS_EN) == 0){
Action_Jump_Spring(id);
return FMRES_IGNORED;
}
else if(get_pcvar_num(SPRING_ACCESS_EN) == 1 && g_UserFlags & ACCESS_ADMIN_FLAG){
Action_Jump_Spring(id);
return FMRES_IGNORED;
}
else if(get_pcvar_num(SPRING_ACCESS_EN) == 2 && g_UserFlags & ACCESS_MULTI_FLAG){
Action_Jump_Spring(id);
return FMRES_IGNORED;
}

//Выводим сообщения об ограниченном доступе если это обычный игрок:
if(get_pcvar_num(SPRING_ACCESS_EN) == 2 && g_UserFlags & ADMIN_USER){
client_print_color(id, print_team_default, "%l", "SPRING_ACCESS_ERR2");
}
else if(get_pcvar_num(SPRING_ACCESS_EN) == 1 && g_UserFlags & (ACCESS_VIP_FLAG|ADMIN_USER)){
client_print_color(id, print_team_default, "%l", "SPRING_ACCESS_ERR1");
}

return FMRES_IGNORED;
}

public Action_Jump_Spring(id) //функция для подстановки события прыжка и тп
{
//Даем звук пружины
emit_sound(get_pcvar_num(SPRING_SOUND_CHECK) == 1 ? id : 0, CHAN_AUTO, SPRING_SND, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);

//Отскок от пружины
new Float:velocity[3];
entity_get_vector(id,EV_VEC_velocity,velocity)

if(g_Player[id] == true || g_Time[id] == -1 || g_Time[id] > 1){
velocity[2] = random_float(get_pcvar_float(SPRINGCAGE_JUMPSPEED_MIN),get_pcvar_float(SPRINGCAG
E_JUMPSPEED_MAX))
}
else{
velocity[2] = random_float(get_pcvar_float(SPRING_JUMPSPEED_MIN),get_pcvar_float(SPRING_JUMPSP
EED_MAX))
}

entity_set_vector(id,EV_VEC_velocity,velocity)

//Задаем значение переменной (для проверки в fw_TakeDamage)
g_NoDamage[id] = id;
//Kill процесс если быстро нажали еще раз (прыгают несколько раз подряд и более..)
remove_task(id);
//Отрубаем бессмертие путем сброса значения массива g_NoDamage
set_task(get_pcvar_float(SPRING_TIME_OFFDAMAGE), "NoDamage_Off", id);

//Даем феерверк при прыжке
if(get_pcvar_num(SPRING_FIREWORK_EN) == 1){
set_task(get_pcvar_float(SPRING_FIREWORK_TIME1), "firework_spring", id);
}
}

public fw_TakeDamage(victim, inflictor, attacker, Float:damage)
{
if(victim == g_NoDamage[victim] && is_user_alive(victim)){
SetHamParamFloat(4, damage - damage)
return HAM_HANDLED;
}

return HAM_IGNORED;
}

public NoDamage_Off(id)
{
g_NoDamage[id] = 0;
}

public cmdSpringMenu(id)
{
if(get_user_flags(id) & ACCESS_ADMIN_FLAG){
spring_makemenu(id);
}
}

public firework_spring(id)
{
for(new j; j < sizeof g_shortSpr; j++)
{
new origin[3];
get_user_origin(id,origin,0)

message_begin(get_pcvar_num(SPRING_FIREWORK_MSG) == 1 ? MSG_ONE : MSG_ALL,SVC_TEMPENTITY,{0,0,0},id)

write_byte(TE_SPRITETRAIL)
write_coord(origin[0]-random_num(6,10))
write_coord(origin[1]-random_num(7,15))
write_coord(origin[2]+random_num(30,70))
write_coord(origin[0]-random_num(5,9))
write_coord(origin[1]-random_num(9,20))
write_coord(origin[2]+random_num(50,100))
write_short(g_shortSpr[j]);
write_byte(random_num(2,7))
write_byte(random_num(7,15))
write_byte(random_num(3,6))
write_byte(random_num(6,20))
write_byte(random_num(20,50))
message_end()
}

if(get_pcvar_num(SPRING_FIREWORK_NUM) == 1){
return PLUGIN_HANDLED;
}
else if(g_FireworkCount <= get_pcvar_num(SPRING_FIREWORK_NUM)){
g_FireworkCount++;
set_task(get_pcvar_float(SPRING_FIREWORK_TIME2), "firework_spring", id)
}
else if(g_FireworkCount > get_pcvar_num(SPRING_FIREWORK_NUM)){
g_FireworkCount = 0
}
return PLUGIN_HANDLED;
}


//Далее менюшки и все что с ними связано-завязано :)

public spring_makemenu(id) //главное меню пружины
{
if(!is_user_connected(id)) return;

new g_SpringMenu[64];

formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_TITLE");
new menu = menu_create(g_SpringMenu, "springmenufunc");
new callback = menu_makecallback("ignormenufunc_2");

formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM1");
menu_additem(menu, g_SpringMenu, "1", .callback = callback);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM2");
menu_additem(menu, g_SpringMenu, "2", .callback = callback);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM3");
menu_additem(menu, g_SpringMenu, "3", .callback = callback);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM4");
menu_additem(menu, g_SpringMenu, "4", .callback = callback);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM5");
menu_additem(menu, g_SpringMenu, "5", .callback = callback);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM6");
menu_additem(menu, g_SpringMenu, "6", 0);
formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_ITEM7");
menu_additem(menu, g_SpringMenu, "7", 0);

formatex(g_SpringMenu, 63, "%L", id, "SPRING_MENU_EXIT");
menu_setprop(menu, MPROP_EXITNAME, g_SpringMenu);

menu_display(id, menu);
}

public springmenufunc(id, menu, item) //внутринности для главного меню
{
if(item == MENU_EXIT){
menu_destroy(menu);
return PLUGIN_HANDLED;
}

new data[6], iName[64];
new iaccess, callback;

menu_item_getinfo(menu, item, iaccess, data, 5, iName, 63, callback);
menu_destroy(menu);

new key = str_to_num(data);

switch(key)
{
case 1: //создание
{
spring_checkmenu(id);
return PLUGIN_HANDLED;
}
case 2: //перемещение
{
spring_movemenu(id);
return PLUGIN_HANDLED;
}
case 3: //удаление одной пружины
{
new ent, body;
get_user_aiming(id, ent, body, 9999);

//проверяем на валидность объекта!
if(!pev_valid(ent)){
client_print_color(id, print_team_default, "%l", "SPRING_OBJECT_ERR");
}
else{
new szClassname[33];

pev(ent, pev_classname, szClassname, 32);
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)

client_print_color(id, print_team_default, "%l", "SPRING_DEL_ONE");
}
}
case 4: //удаление всех пружин на карте
{
new ent;

while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "Spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "Q-Cage_spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "W-Cage_spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "E-Cage_spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "R-Cage_spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "T-Cage_spring"))){
set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME)
g_SpringEnt = ent
}

if(g_SpringEnt == 0){
client_print_color(id, print_team_default, "%l", "SPRING_DEL_ERROR");
ent = 0
g_SpringEnt = 0
}
else{
client_print_color(id, print_team_default, "%l", "SPRING_DEL_ALL");
ent = 0
g_SpringEnt = 0
}
}
case 5: //сохранение точек пружин на карте (для последуещего воспроизведения (расстановки))
{
new mapname[MAX_MAPNAME_LENGTH], springfile[128];
get_mapname(mapname, MAX_MAPNAME_LENGTH-1);

spring_get_configsdir(springfile, 127);
formatex(springfile, 127, "%s/%s/%s.cfg", springfile, SPRING_SAVE, mapname)

if(file_exists(springfile)){
delete_file(springfile);
}

new ent, Float:vOrigin[3], szData[42];
new f = fopen(springfile, "at");

while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "Spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "S %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "Q-Cage_spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "Q %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "W-Cage_spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "W %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "E-Cage_spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "E %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "R-Cage_spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "R %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}
while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "T-Cage_spring"))){
pev(ent, pev_origin, vOrigin)
formatex(szData, 41, "T %f %f %f^n", vOrigin[0], vOrigin[1], vOrigin[2])
fputs(f, szData)

g_SpringEnt = ent
}

if(g_SpringEnt == 0){
client_print_color(id, print_team_default, "%l", "SPRING_SAVE_ERROR");
ent = 0
g_SpringEnt = 0
}
else{
client_print_color(id, print_team_default, "%l", "SPRING_SAVE_ACTION");
ent = 0
g_SpringEnt = 0
}

fclose(f);
}
case 6: //меню перемещения игрока в клетку
{
new Float:p_Origin[3], ent;

while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "T-Cage_spring"))){
pev(ent, pev_origin, p_Origin)
}

ent = 0;
p_Origin[2] += 60;
g_pOrigin[id] = p_Origin; //тп игрока через меню

spring_playermenu(id);
return PLUGIN_HANDLED;
}
case 7: //меню досрочного освобождения из клетки
{
spring_menufreedom(id);
return PLUGIN_HANDLED;
}
}

spring_makemenu(id);
return PLUGIN_HANDLED;
}

public spring_menufreedom(id) //меню выбора игроков для досрочного освобождения
{
if(!is_user_connected(id)) return;

new g_SpringMenuFreedom[64];

formatex(g_SpringMenuFreedom, 63, "%L", id, "SPRING_MENUFREEDOM_TITLE");
new menu = menu_create(g_SpringMenuFreedom, "springfreedomfunc");
new callback = menu_makecallback("ignormenufunc_3");

new szName[MAX_NAME_LENGTH], szInfo[3], iPlayers[MAX_PLAYERS], iPlayer, iNum;
get_players_ex(iPlayers, iNum, GetPlayers_ExcludeDead|GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV);

for(new i; i < iNum; i++){
iPlayer = iPlayers[i];
szInfo[0] = iPlayer;

get_user_name(iPlayer, szName, charsmax(szName));
menu_additem(menu, szName, szInfo, .callback = callback);
}

formatex(g_SpringMenuFreedom, 63, "%L", id, "SPRING_MENU_BACK");
menu_setprop(menu, MPROP_BACKNAME, g_SpringMenuFreedom);
formatex(g_SpringMenuFreedom, 63, "%L", id, "SPRING_MENU_NEXT");
menu_setprop(menu, MPROP_NEXTNAME, g_SpringMenuFreedom);
formatex(g_SpringMenuFreedom, 63, "%L", id, "SPRING_MENU_EXIT");
menu_setprop(menu, MPROP_EXITNAME, g_SpringMenuFreedom);

menu_display(id, menu);
}

public springfreedomfunc(id, menu, item) //внутринности для меню досрочного освобождения из клетки
{
if(item == MENU_EXIT){
menu_destroy(menu);
spring_makemenu(id);
return PLUGIN_HANDLED;
}

new szInfo[3], buffer;

menu_item_getinfo(menu, item, buffer, szInfo, charsmax(szInfo), .callback = buffer);
menu_destroy(menu);

new iPlayer = szInfo[0];
Freedom_Player(id, iPlayer);

return PLUGIN_HANDLED;
}

public Freedom_Player(id, iPlayer) //отпускаем игрока
{
g_Player[iPlayer] = false;
g_Time[iPlayer] = 0;

client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_FREEDOM3", iPlayer, id);
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_FREEDOM2");
client_print_color(id, print_team_default, "%l", "SPRING_CAGE_FREEDOMADMIN", iPlayer);

log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG4", id, iPlayer);
spring_menufreedom(id);
}

public spring_checkmenu(id) //выбор пружины или клетки-пружины
{
if(!is_user_connected(id)) return;

new g_SpringCheckMenu[64];

formatex(g_SpringCheckMenu, 63, "%L", id, "SPRING_CHECKMENU_TITLE");
new menu = menu_create(g_SpringCheckMenu, "springcheckfunc");

formatex(g_SpringCheckMenu, 63, "%L", id, "SPRING_CHECKMENU_ITEM1");
menu_additem(menu, g_SpringCheckMenu, "1", 0);
formatex(g_SpringCheckMenu, 63, "%L", id, "SPRING_CHECKMENU_ITEM2");
menu_additem(menu, g_SpringCheckMenu, "2", 0);

formatex(g_SpringCheckMenu, 63, "%L", id, "SPRING_MENU_BACK");
menu_setprop(menu, MPROP_EXITNAME, g_SpringCheckMenu);

menu_display(id, menu);
}

public springcheckfunc(id, menu, item) //внутринности для меню выбора клетки или пружины
{
if(item == MENU_EXIT){
menu_destroy(menu);
spring_makemenu(id);
return PLUGIN_HANDLED;
}

new data[6], iName[64];
new iaccess, callback;

menu_item_getinfo(menu, item, iaccess, data, 5, iName, 63, callback);
menu_destroy(menu);

new key = str_to_num(data);

switch(key)
{
case 1: //создание пружина борда
{
makeBox(id, 1, "Spring");
client_print_color(id, print_team_default, "%l", "SPRING_CREATED");
}
case 2: //создание из частей клетки пружины
{
new ent, check;

while((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "Q-Cage_spring"))){
check = ent;
}

if(check != 0){
client_print_color(id, print_team_default, "%l", "SPRING_CAGE_CHECK");
ent = 0;
check = 0;
return PLUGIN_HANDLED;
}

makeBox(id, 2, "Q-Cage_spring");
makeBox(id, 3, "W-Cage_spring");
makeBox(id, 4, "E-Cage_spring");
makeBox(id, 5, "R-Cage_spring");
makeBox(id, 6, "T-Cage_spring");
client_print_color(id, print_team_default, "%l", "SPRING_CAGE_CREATED");
}
}

spring_checkmenu(id);
return PLUGIN_HANDLED;
}

public spring_movemenu(id) //меню настроек (перемещение)
{
if(!is_user_connected(id)) return;

new g_SpringMoveMenu[64];

formatex(g_SpringMoveMenu, 63, "%L", id, "SPRING_MOVEMENU_TITLE");
new menu = menu_create(g_SpringMoveMenu, "springmovefunc");

menu_additem(menu, "X++", "1", 0);
menu_additem(menu, "X--", "2", 0);
menu_additem(menu, "Y++", "3", 0);
menu_additem(menu, "Y--", "4", 0);
menu_additem(menu, "Z++", "5", 0);
menu_additem(menu, "Z--", "6", 0);

formatex(g_SpringMoveMenu, 63, "%L", id, "SPRING_MENU_BACK");
menu_setprop(menu, MPROP_EXITNAME, g_SpringMoveMenu);

menu_display(id, menu);
}

public springmovefunc(id, menu, item) //внутринности для меню перемещения
{
if(item == MENU_EXIT){
menu_destroy(menu);
spring_makemenu(id);
return PLUGIN_HANDLED;
}

new data[6], iName[64];
new iaccess, callback;

menu_item_getinfo(menu, item, iaccess, data, 5, iName, 63, callback);
menu_destroy(menu);

moveBox(id, str_to_num(data));

spring_movemenu(id);
return PLUGIN_HANDLED;
}

public spring_playermenu(id) //меню выбора игрока для перемещения в клетку
{
if(!is_user_connected(id)) return;

new g_SpringPlayerMenu[64];

formatex(g_SpringPlayerMenu, 63, "%L", id, "SPRING_PLAYERMENU_TITLE");

new menu = menu_create(g_SpringPlayerMenu, "springplayerfunc");
new callback = menu_makecallback("ignormenufunc_1");

new szName[MAX_NAME_LENGTH], szInfo[3], iPlayers[MAX_PLAYERS], iPlayer, iNum;
get_players_ex(iPlayers, iNum, GetPlayers_ExcludeDead|GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV);

for(new i; i < iNum; i++){
iPlayer = iPlayers[i];
szInfo[0] = iPlayer;

get_user_name(iPlayer, szName, charsmax(szName));
menu_additem(menu, szName, szInfo, .callback = callback);
}

formatex(g_SpringPlayerMenu, 63, "%L", id, "SPRING_MENU_BACK");
menu_setprop(menu, MPROP_BACKNAME, g_SpringPlayerMenu);
formatex(g_SpringPlayerMenu, 63, "%L", id, "SPRING_MENU_NEXT");
menu_setprop(menu, MPROP_NEXTNAME, g_SpringPlayerMenu);
formatex(g_SpringPlayerMenu, 63, "%L", id, "SPRING_MENU_EXIT");
menu_setprop(menu, MPROP_EXITNAME, g_SpringPlayerMenu);

menu_display(id, menu);
}

public springplayerfunc(id, menu, item) //внутринности для меню перемещения игрока в клетку
{
if(item == MENU_EXIT){
menu_destroy(menu);
spring_makemenu(id);
return PLUGIN_HANDLED;
}

new szInfo[3], buffer;

menu_item_getinfo(menu, item, buffer, szInfo, charsmax(szInfo), .callback = buffer);
menu_destroy(menu);

new iPlayer = szInfo[0];

if(get_pcvar_num(SPRING_CAGETIME_EN) == 1){
g_CheckPlayer = iPlayer;
spring_timemenu(id);
}
else{
g_Time[iPlayer] = -1;
Teleport_Player(id, iPlayer);
}

return PLUGIN_HANDLED;
}

public spring_timemenu(id) //меню выбора времени для перемещения игрока в клетку на время
{
if(!is_user_connected(id)) return;

new g_SpringTimeMenu[64];

formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMEMENU_TITLE");

new menu = menu_create(g_SpringTimeMenu, "springtimefunc");

formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMECAGE_1", get_pcvar_num(SPRING_CAGETIME_1));
menu_additem(menu, g_SpringTimeMenu, "1", 0);
formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMECAGE_2", get_pcvar_num(SPRING_CAGETIME_2));
menu_additem(menu, g_SpringTimeMenu, "2", 0);
formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMECAGE_3", get_pcvar_num(SPRING_CAGETIME_3));
menu_additem(menu, g_SpringTimeMenu, "3", 0);
formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMECAGE_4", get_pcvar_num(SPRING_CAGETIME_4));
menu_additem(menu, g_SpringTimeMenu, "4", 0);
formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_TIMECAGE_5", get_pcvar_num(SPRING_CAGETIME_5));
menu_additem(menu, g_SpringTimeMenu, "5", 0);

formatex(g_SpringTimeMenu, 63, "%L", id, "SPRING_MENU_BACK");
menu_setprop(menu, MPROP_BACKNAME, g_SpringTimeMenu);

menu_display(id, menu);
}

public springtimefunc(id, menu, item) //внутринности для меню выбора времени на которое перемещается игрок
{
if(item == MENU_EXIT){
menu_destroy(menu);
return PLUGIN_HANDLED;
}

new data[6], iName[64];
new iaccess, callback;

menu_item_getinfo(menu, item, iaccess, data, 5, iName, 63, callback);
menu_destroy(menu);

new key = str_to_num(data);

switch(key)
{
case 1: g_Time[g_CheckPlayer] = time() + get_pcvar_num(SPRING_CAGETIME_1) * 60; //время трансформируемое в минуты 1
case 2: g_Time[g_CheckPlayer] = time() + get_pcvar_num(SPRING_CAGETIME_2) * 60; //время трансформируемое в минуты 2
case 3: g_Time[g_CheckPlayer] = time() + get_pcvar_num(SPRING_CAGETIME_3) * 60; //время трансформируемое в минуты 3
case 4: g_Time[g_CheckPlayer] = time() + get_pcvar_num(SPRING_CAGETIME_4) * 60; //время трансформируемое в минуты 4
case 5: g_Time[g_CheckPlayer] = time() + get_pcvar_num(SPRING_CAGETIME_5) * 60; //время трансформируемое в минуты 5
}

Teleport_Player(id, g_CheckPlayer);
return PLUGIN_HANDLED;
}

public Teleport_Player(id, iPlayer) //Телепорт в клетку
{
set_pev(iPlayer, pev_velocity, Float:{0.0, 0.0, 0.0})
set_pev(iPlayer, pev_origin, g_pOrigin[id])

g_Player[iPlayer] = true;

new iPlayers[MAX_PLAYERS], iPlayerCount;
get_players_ex(iPlayers, iPlayerCount, GetPlayers_ExcludeDead|GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV);

for(new i; i < iPlayerCount; i++){
if(iPlayers[i] != iPlayer) client_print_color(iPlayers[i], print_team_default, "%l", "SPRING_CAGE_INFOALL", iPlayer, id);
}

client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_INFOPUNISHMENT1", iPlayer, id);
client_print_color(iPlayer, print_team_default, "%l", "SPRING_CAGE_INFOPUNISHMENT2");

if(get_pcvar_num(SPRING_CAGETIME_EN) == 1){
new Min = g_Time[iPlayer] - time();
log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG5", id, iPlayer, Min / 60);
}
else{
log_to_file(g_szLogPath, "%L", LANG_PLAYER, "SPRING_MULTI_LOG6", id, iPlayer);
}

spring_playermenu(id);
}

public ignormenufunc_1(id, menu, item) //игнорим кого уже переместили или у игрока флаг иммуна (для меню перемещения) или мертв
{
new szInfo[3], buffer;
menu_item_getinfo(menu, item, buffer, szInfo, charsmax(szInfo), .callback = buffer);

new iPlayer = szInfo[0];

if(!is_user_alive(iPlayer)) return ITEM_DISABLED;
if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1 || get_user_flags(iPlayer) & ACCESS_CAGE_FLAG) return ITEM_DISABLED;

return ITEM_IGNORE;
}

public ignormenufunc_2(id, menu, item) //игнорим основные настройки от обычных админов
{
if(get_user_flags(id) & (ACCESS_ADMIN_FLAG|ACCESS_MENU_FLAG) == (ACCESS_ADMIN_FLAG|ACCESS_MENU_FLAG)){
return ITEM_IGNORE;
}
else if(get_user_flags(id) & ACCESS_ADMIN_FLAG){
return ITEM_DISABLED;
}

return ITEM_IGNORE;
}

public ignormenufunc_3(id, menu, item) //игнорим игроков которые не в клетке (меню досрочное освобождение) и с иммуном
{
new szInfo[3], buffer;
menu_item_getinfo(menu, item, buffer, szInfo, charsmax(szInfo), .callback = buffer);

new iPlayer = szInfo[0];

if(get_user_flags(iPlayer) & ACCESS_CAGE_FLAG){
return ITEM_DISABLED;
}
else if(g_Player[iPlayer] == true || g_Time[iPlayer] == -1 || g_Time[iPlayer] > 1){
return ITEM_IGNORE;
}

return ITEM_IGNORE;
}

public spring_get_configsdir(name[], len) //проверка на директории
{
new g_Dir[64];
get_localinfo("amxx_configsdir", g_Dir, 63)

return formatex(name, len, "%s/%s", g_Dir, SPRING_DIR)
}


//Далее главные-системные функции (создание, перемещение и тп):

stock makeBox(id, num, const szClassname[], Float:pOrigin[3]={0.0, 0.0, 0.0})
{
new ent = engfunc(EngFunc_CreateNamedEntity, SPRING_BUTTON);

//проверяем на валидность объекта!
if(!pev_valid(ent)){
client_print_color(id, print_team_default, "%l", "SPRING_OBJECT_ERR")
return PLUGIN_HANDLED;
}

set_pev(ent, pev_classname, szClassname)
set_pev(ent, pev_solid, SOLID_BBOX)
set_pev(ent, pev_movetype, MOVETYPE_NONE)
set_pev(ent, pev_target)

switch(num)
{
case 1:
{
engfunc(EngFunc_SetModel, ent, SPRING_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_MIN, SPRING_MAX)

fm_set_rendering(ent, kRenderFxGlowShell, random_num(10,255), random_num(10,255), random_num(10,255), kRenderNormal, get_pcvar_num(SPRING_RENDER_AMOUNT))
}
case 2:
{
engfunc(EngFunc_SetModel, ent, SPRING_CAGE1_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_CAGE1_MIN, SPRING_CAGE1_MAX)
}
case 3:
{
engfunc(EngFunc_SetModel, ent, SPRING_CAGE2_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_CAGE2_MIN, SPRING_CAGE2_MAX)
}
case 4:
{
engfunc(EngFunc_SetModel, ent, SPRING_CAGE3_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_CAGE3_MIN, SPRING_CAGE3_MAX)
}
case 5:
{
engfunc(EngFunc_SetModel, ent, SPRING_CAGE4_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_CAGE4_MIN, SPRING_CAGE4_MAX)
}
case 6:
{
engfunc(EngFunc_SetModel, ent, SPRING_CAGE5_MDL)
engfunc(EngFunc_SetSize, ent, SPRING_CAGE5_MIN, SPRING_CAGE5_MAX)
}
}

if(id){ //ставит игрок
new Float:vOrigin[3];
fm_get_aim_origin(id, vOrigin)
vOrigin[2] += 22.0 //положить на пол
engfunc(EngFunc_SetOrigin, ent, vOrigin);
}
else{ //ставит функция read_spring
engfunc(EngFunc_SetOrigin, ent, pOrigin)
}

return PLUGIN_HANDLED;
}

stock moveBox(id, mode) //перемещение пружины
{
new ent, body, szClassname[33];
get_user_aiming(id, ent, body, 9999);

//проверяем на валидность объекта!
if(!pev_valid(ent)){
client_print_color(id, print_team_default, "%l", "SPRING_MOVE_ERR");
return PLUGIN_HANDLED;
}

pev(ent, pev_classname, szClassname, 32);

new Float:vOrigin[3];
pev(ent, pev_origin, vOrigin);

switch(mode)
{
case 1: vOrigin[0] += get_pcvar_float(SPRING_MOVE_CVAR);
case 2: vOrigin[0] -= get_pcvar_float(SPRING_MOVE_CVAR);
case 3: vOrigin[1] += get_pcvar_float(SPRING_MOVE_CVAR);
case 4: vOrigin[1] -= get_pcvar_float(SPRING_MOVE_CVAR);
case 5: vOrigin[2] += get_pcvar_float(SPRING_MOVE_CVAR);
case 6: vOrigin[2] -= get_pcvar_float(SPRING_MOVE_CVAR);
}

engfunc(EngFunc_SetOrigin, ent, vOrigin);
return PLUGIN_HANDLED;
}

stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16) //свечение модели
{
new Float:RenderColor[3];

RenderColor[0] = float®;
RenderColor[1] = float(g);
RenderColor[2] = float(b);

set_pev(entity, pev_renderfx, fx);
set_pev(entity, pev_rendercolor, RenderColor);
set_pev(entity, pev_rendermode, render);
set_pev(entity, pev_renderamt, float(amount));

return 1;
}

stock fm_get_aim_origin(index, Float:origin[3]) //fm_get_aim_origin - портирована из функции ядра AMXX get_user_origin(..., 3)
{
new Float:start[3], Float:view_ofs[3];

pev(index, pev_origin, start);
pev(index, pev_view_ofs, view_ofs);
xs_vec_add(start, view_ofs, start);

new Float:dest[3];

pev(index, pev_v_angle, dest);
engfunc(EngFunc_MakeVectors, dest);
global_get(glb_v_forward, dest);
xs_vec_mul_scalar(dest, 9999.0, dest);
xs_vec_add(start, dest, dest);

engfunc(EngFunc_TraceLine, start, dest, 0, index, 0);
get_tr2(0, TR_vecEndPos, origin);

return 1;
}

stock fm_set_user_godmode(index, godmode = 0) //Для бессмертия
{
set_pev(index, pev_takedamage, godmode == 1 ? DAMAGE_NO : DAMAGE_AIM);
return 1;
}






Видеообзор (мод: 'Пружина-Клетка'):



Обновления версий:

Обновление до версии (2.0.1)

[Added]:

- Добавлена новая модель (spring-new.mdl), более оптимизированная версия пружинного борда. (спасибо quasar)​
- Добавлен новый #define SPRING_NEW_MODEL (если закомментирован, то используется старая модель пружинного борда, если откомментировано, то используется новая модель)​
- Переход на трех значную систему версий. :good2:​

Обновление до версии (2.0)

[Added]:

- Добавлен новый квар, который устанавливает на сколько по дальности перемещать объекты по координатам. (значение для функции перемещения (подстановка в коде, дальность, чем больше значение, тем быстрее Вы передвинете объект)​
- Вывод логов сделаны мультиязычными (спасибо: ребятам с форума Dev-Cs (w0w, the_hunter) за пояснения).​

[Fixed]:

- Были внесены изменения в LANG файл.​
- Были внесены изменения в CFG файл.​

Обновление до версии (1.9)

[Added]:

- Реализована возможность убивать игрока(ов) в клетке через заданное время (дабы избежать простаивания раунда, если все игроки за клеткой мертвы и подобных случаев, игроки и заключенные в клетке не зависят друг от друга).​
- Добавлены новые переменные, квары, функции.​
- Сделано событие смерти игроков в клетке без сообщения в верхнем правом углу, т.е игроки в клетке будут незаметно убиты, будто их и нет в игре (не мешают игровому процессу остальным).​
- Реализовано эффектная смерть в клетке игрока.​
- Добавлена const переменная (флаг иммунитета от попадания в клетку).​
- Добавлены новые сообщения в LANG файл.​
- Добавлены новые квары в CFG файл.​

Обновление до версии (1.8)

[Fixed]:

- Исправлена утечка в меню (!is_user_connected) перемещено в другое место во всех меню. Спасибо: Denzer​
- В событии Ham_TakeDamage, далее выполняемой функции > 'fw_TakeDamage' изменена проверка, убрано (is_user_connected) и оставлено только (is_user_alive), так как (is_user_alive), проверяет сначала подключен ли игрок.​

Обновление до версии (1.7)

[Optimized]:

- Оптимизирован код в части циклов while, подправлены скобки, освобождение места в пользу меньших строк кода.​

Обновление до версии (1.6)

[Added]:

- Добавлены требования: ReSemiclip (желательно) или ReGameDLL (mp_kill_filled_spawn), иначе Unstuck или Stuck RBS. (что бы было выталкивание игрока из игрока)​

[Fixed]:

- Подправлены комментарии или в некоторых местах где и так все понятно убраны вообще.​
- Исправлено вызов меню из другого меню (когда освобождаешь игрока из клетки (меню освобождение), то после вызывалось меню телепортации в клетку).​
- Убран из события SPAWN, цикл и функция user_slap (вместо этого добавлены в описание плагина необходимые требования для использования (желательно)).​

[Optimized]:

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

Обновление до версии (1.5)

!-- [Very Critical Update] --!

[Fixed]:

- В ходе длительной проверки на сервере с реальными игроками, были обнаружены баги.​
- Правки в коде (часть игнора игроков в меню перемещения и освобождения; get_user_flags(id) заменено на get_user_flags(iPlayer)), игнорились все (из-за id)​
- Правки в коде (часть события spawn, добавлена проверка поиска по классу, так как игроки не телепортировались в новом раунде в клетку!)​
- Критическое обновление!​

Обновление до версии (1.4)

!-- [Global Update] --!

[Added]:

- Добавлена отдельная система этого плагина, под названием: 'Spring Cage'; Rus: 'Пружинная клетка'.
- Для чего и как работает: После создания клетки-пружины на карте, можно поместить любого игрока через доп. меню выбора. (это может быть наказание или еще что-то; флуд, спам, подумать над поведением).
- Добавлена возможность разместить игрока в клетку на время (выбирается в меню), если игрок находится в клетке, и настанет новый раунд, он всеравно окажется там же, если его время выхода еще непришло!​
- Созданы необходимые квары, функции, меню и тп.​
- Создано меню телепорта игрока в клетку.​
- Внедрена система времени на которое перемещается игрок в клетку​
- Добавлена команда для чата, узнать сколько времени перемещенному в клетку осталось там сидеть. (say /freedom)​
- Добавлены новые переменные, счетчики + массивы и переключатели bool, для разных функций связанных с клеткой. (гибче настройка под Ваши нужды)​
- Добавлено: Игрок из клетки может попросить прощения у присутствующих админов на сервере, админам придет уведомление, что игрок в клетке. (say /pardon)​
- Добавлено: Меню для досрочного освобождения из клетки (для админов)​
- Реализовано сохранение тех игроков, которые хотят обойти клетку. (т.е при выходе инфа сохраняется, и при входе такого игрока он опять окажется в клетке), спасибо: BlackSignature​

[Fixed]:

- Все логи теперь выводятся в отдельный файл. (logs/spring/)​

[Optimized]:

- Оптимизация кода по замечаниям. (с прежней версии)​
- Правки в коде с учетом новых переменных. (+ оптимизация)​

Обновление без изменения версии

- У файла с расширением '.sma' была кривая кодировка.​

Обновление до версии (1.3)

[Added]:
- Добавлено уничтожение менюшек в еще несколько частей кода (menu_destroy(menu);), дабы не утекала память!, спасибо: Mistrick​

[Fixed]:
- Исправлен код в части выдачи прыжка совместно с fw_TakeDamage, конкретно переменная g_NoDamage сделана массивом, так как, если несколько прыгают на пружине сразу, все бы ломалось, спасибо: Denzer, Mistrick​

[Update is critical]:
- Опять же, обновление критично из-за утечки памяти (возможны лаги на предыдущих версиях), обязательно к обновлению!​

Обновление до версии (1.2)

[Added]:
- Функция SendAudio заменена на Emit_Sound, что бы звук не распростронялся на всю карту, спасибо: Jumper, w0w​
- Добавлен новый квар (SPRING_SOUND_CHECK) == выбор между слышимостью всем или 1 игроку который использует звук. (0/1 - всем/одному; настройка в .cfg), спасибо: Jumper​

[Fixed]:
- Добавлено уничтожение меню после его использования (menu_destroy), дабы не утекала память (могло привести к лагам на сервере и тп), спасибо: Mistrick​

[Update is critical]:
- Критичное обновление (рекомендация обновиться, так как, обновление касающееся утечки памяти не стоит игнорировать.)​

Обновление до версии (1.1)

[Added]:
- Реализовано мультиязычное меню (теперь пункты меню в LANG файле)​
- Добавлен квар (sp_time_offdmg). время до отключения бессмертия (бессмертие действует только для victim, т.е для игрока который прыгает. Другие смогут его убить.)​

[Fixed]:
- Правка кода функции феерверка (был обнаружен потанциальный краш), cпасибо: voed​
- Небольшая правка кода (изменил расположение g_UserFlags, удалил return FMRES_IGNORED; где вывод сообщений), спасибо: d3m37r4, fantom​
- Изменено бессмертие (fm_set_user_godmode) на отлов события (Ham_TakeDamage), дабы в полете урон можно было наносить другим игрокам, спасибо: Denzer, WILL_BE​

[Optimized]:
- Из внутриностей менюшек убраны не нужные значения, которые лишь захломляли код, спасибо: fl0wer​
- Из кода убраны переменные и значения которые больше не нужны, а также добавлено нужное новое.​



Прикрепленный файл  Spring.zip ( 402,37 килобайт ) Кол-во скачиваний: 41
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 4 раз
   Цитировать сообщение
Статус пользователя wellasg00d
сообщение 19.10.2019, 11:17
Сообщение #2


Стаж: 10 лет
Город: Москва

Сообщений: 3
Благодарностей: 8
Полезность: 0

Здравствуйте! Ув. Форумчане!

К сожалению, у меня пока что нету прав редактировать первый пост для изменений оформления и добавления новой версии.
По этому, обновление буду выкладывать по средствам сообщений.

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

Информация обновления (ver 2.0.2)

* - ver 2.0.2:
- Поправлен код в месте выбора времени на которое сажать в клетку (switch заменен на легкую конструкцию кода) спасибо: flower, Denzer (оптимизация).
- Добавлен выбор между объектами перед перемещением. (новое меню и функции).
- Изменен способ перемещения для клетки. (будут двигаться сразу все части клетки одновременно. раньше они двигались по одной и криво), спасибо за помощь в реализации: zhorzh78.
- Изменен способ удаления частей клетки (изменена конструкия кода, его стало меньше, переделана работа с циклами), спасибо за помощь в реализации: zhorzh78, flower.
- Изменен способ сохранения частей клетки (переработан код, его стало меньше).
- Добавлен новый #include <fakemeta_util> (дабы неплодить лишнии stock, раз много их используется в плугине оттуда).
- Добавлена новая проверка на класснейм (фича от удалений посторонних объектов на карте, которые можно нечайно удалить из-за особенностей карты.), спасибо за идею: BlackSignature, jumper.
- Были внесены изменения в LANG файл. (добавлены новые строки, редактирование старых)
- Некоторые переменные (массивы), переделаны с оптимизацией (например, обычные переменные для подстановки, превратились в двухмерный массив, сократился код)
- Убраны лишнии строки захломаляющии код (которые по сути не нужны, например код в plugin_init по отключениям не нужных карт)
- Переработано создание пунктов во всех меню. (сокращен код)
- Исправлен баг с созданием 2го объекта если была пустая строка в файле сохранений координат, спасибо за помощь: BlackSignature
- Убран #include <xs>, так как #include <fakemeta_util> сам его цепляет.
- Добавлены новые #define позволяющие отключить скачивание пружино клетки или пружино-борда игроками, в зависимости от того, какой мод Вам нужен на сервере. (для удобства)
-- Пояснение:
--- Минимум 1 #define среди #define SPRING_MODE_CAGE и SPRING_MODE_BOARD, должен быть откомментирован.
--- Если закомментирован #define SPRING_MODE_BOARD, то модель не качается, соответсвенно плугин нужно использовать только функции пружино-клетки (пункты меню настроек).
--- Если закомментирован #define SPRING_MODE_CAGE, то модели не качаются, соотвественно плугин нужно использовать только для пружино-борда (пункты меню настроек).
--- Если оба define откомментированы, то все модели качаются игроками, соотвественно плугин можно использовать целиком. (все пункты меню настроек).
--- Если какой-то из #define среди #define SPRING_MODE_CAGE и SPRING_MODE_BOARD откомментирован, то нельзя нажимать пункты меню закомментированного мода!!! (иначе будут ошибки)
--- Т.е: если пружино-борд, то не трогаем пункты (перемещение в клетку, создание пружины-клектки, перемещение пружино-клетки), иначе, не трогаем пункты (создание пружино-борда, перемещение пружино-борда)
- Добавлен новый #define позволяющий отключить скачивание спрайтов от феерверка. (для удобства)
-- Пояснение:
--- Если закомментирован #define SPRING_FIREWORK, то спрайты не качаются, соответственно феерверк работать не будет.
--- Если откомментирован #define SPRING_FIREWORK, то спрайты качаются, соответственно возможность работы феерверка будет, можно использовать настройки кваров феерверка.
Информация обновления (ver 2.0.3)

* - ver 2.0.3:
- Исправлена функция .callback, (была ошибка в условие скрытия меню (просвечивания) от обычных админов, суть в том, если мод клетка, то обычным админам (ACCESS_ADMIN_FLAG) оставлять только 2 пункта (перемещение в клетку и освобождение из клетки), а системное просвечивать. (условие: if(str_to_num(data) > 5), заменено на: if(str_to_num(data) <= 5), пояснение: пункты 6 и 7, как раз необходимо оставлять, а остальное просвечивать).

good.gif

Скачать обнову:
Прикрепленный файл  Spring.zip ( 402,9 килобайт ) Кол-во скачиваний: 27
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 3 раз
   + Цитировать сообщение
  Ответить в данную темуНачать новую тему
 
0 пользователей и 1 гостей читают эту тему: