Jump to content

xYaroslavGTx

Administrators
  • Content Count

    8
  • Joined

  • Last visited

Community Reputation

1,001 Excellent

1 Follower

About xYaroslavGTx

  • Rank
    Newbie
  • Birthday 12/13/1999

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. MTA позволяет манипулировать с различными ограничениями ID (максимальное количество файлов - 65533) и размером карты мира при помощи сторонних плагинов, в данном случае будем использовать limit adjuster от fastman92. Для реализации данного способа придется пересобрать клиент из исходников. Первым делом скачиваем сам limit adjuster (версия должна быть 5.7 или новее) и распаковываем в папку с игрой. Запускаем Visual Studio и идем в Client\core\Core.cpp После строки SetCurrentDirectory(WorkingDirectory.c_str()); Добавляем // Load the FLA (old method) LoadLibraryA("$fastman92limitAdjusterX64.asi"); Можно использовать плагин для x64-систем если вы собираетесь запускать клиент на x64-системе. После редактирования файла должно получиться вот так Далее собираем или пересобираем проект, тыкаем Сборка -> Собрать решение и ждем пока соберется билд. Обратите внимание: перед сборкой должна быть выбрана конфигурация Nightly Win32 Желательно запустить одиночную игру после установки плагина, чтобы сгенерировать конфигурационный файл, либо скопируйте его вручную. Результат: Обычный клиент MTA SA Клиент с установленным limit adjuster (стандартные параметры) Все настройки плагина находятся в fastman92limitAdjuster_GTASA.ini
  2. xYaroslavGTx

    pAttach

    Скрипт: https://mtaresource.ru/resource?rid=473 Оригинальная статья: https://forum.mtasa.com/topic/129019-rel-pattach-optimized-bone-attach/ pAttach Версия 1.0 Оптимизированная версия bone attach с использованием новых функций и эвентов из последнего обновления клиента MTA. Использование старых функций из обычного bone_attach невозможно! Экспортируемые функции: attach - прикрепление элемента к кости педа или игрока. bool attach(element Element, element Ped, int/string Bone [, float xPosOffset = 0, float yPosOffset = 0, float zPosOffset = 0, float xRotOffset = 0, float yRotOffset = 0, float zRotOffset = 0]) Обязательные параметры: - Element: Элемент, который вы хотите присоединить - Ped: Элемент, к которому будет присоеденен другой элемент - Bone: Имя или номер кости, к которой будет присоединен элемент Опциональные параметры: - xPosOffset: Смещение элемента по оси X - yPosOffset: Смещение элемента по оси Y - zPosOffset: Смещение элемента по оси Z - xRotOffset: Вращение элемента по оси X - yRotOffset: Вращение элемента по оси Y - zRotOffset: Вращение элемента по оси Z Возвращает true если элемент успешно присоединен, в остальных случаях false (клиентская функция) detach - открепление элемента bool detach(element Element) Обязательные параметры: - Element: Элемент, который вы хотите отсоединить Возвращает true если элемент успешно отсоединен, в остальных случаях false (клиентская функция) detachAll - отсоединяет все прикрепленные элементы от педа или игрока bool detachAll(element Ped) Обязательные параметры: - Element: Элемент, от которого будем отсоединять Возвращает true если элемент успешно отсоединен, в остальных случаях false (клиентская функция) setPositionOffset - устанавливает смещение для уже присоединенного элемента bool setPositionOffset(element Element [, float xPosOffset = 0, float yPosOffset = 0, float zPosOffset = 0 ]) Обязательные параметры: - Element: Элемент, смещение которого нужно изменить Опциональные параметры: - xPosOffset: Смещение элемента по оси X - yPosOffset: Смещение элемента по оси Y - zPosOffset: Смещение элемента по оси Z Возвращает true если выполнено успешно, в остальных случаях false (клиентская функция) setRotationOffset - устанавливает вращение для уже присоединенного элемента bool setRotationOffset(element Element [, float xRotOffset = 0, float yRotOffset = 0, float zRotOffset = 0 ]) Обязательные параметры: - Element: Элемент, вращение которого нужно изменить Опциональные параметры: - xRotOffset: Вращение элемента по оси X - yRotOffset: Вращение элемента по оси Y - zRotOffset: Вращение элемента по оси Z Возвращает true если выполнено успешно, в остальных случаях false (клиентская функция) invisibleAll - делает все прикрепленные элементы видимыми или невидимыми bool invisibleAll(element Element, bool State) Обязательные параметры: - Element: Элемент, видимость объектов на котором нужно изменить - State: Состояние видимости (true - видимый | false - невидимый) Возвращает true если выполнено успешно, в остальных случаях false (клиентская функция) isAttached - проверяет, присоединен ли объект к чему нибудь bool isAttached(element Element) Обязательные параметры: - Element: Элемент, состояние которого мы хотим узнать Возвращает true если выполнено успешно, в остальных случаях false (клиентская функция) getDetails - возвращает информацию об прикрепленном элементе в виде таблицы table getDetails(element Element) Обязательные параметры: - Element: Элемент, информацию о котором мы хотим узнать Возвращает таблицу если элемент существует и присоединен, в остальных случаях false (клиентская функция) Как использовать: [Сервер] прикрепление рюкзака (парашюта) к игроку addCommandHandler("testbackpack", function(player) local object = createObject(371, 0, 0, 0) exports.pAttach:attach(object, player, "backpack", 0, -0.15, 0, 90, 0, 0) end) ID и имена костей: Имена backpack: Используется для присоединения элемента в качестве рюкзака weapon: Используется для присоединения элемента в качестве оружия (правая рука) head: Голова neck: Шея left-shoulder: Левое плечо right-shoulder: Правое плечо spine: Позвоночник pelvis: Таз left-hip: Левое бедро right-hip: Правое бедро left-elbow: Левый локоть right-elbow: Правый локоть left-wrist: Левое запястье right-wrist: Правое запястье left-thumb: Левый большой палец right-thumb: Правый большой палец left-hand: Левая ладонь right-hand: Правая ладонь left-knee: Левое колено right-knee: Правое колено left-tankle: Left tankle right-tankle: Right tankle left-foot: Левая ступня right-foot: Правая ступня ID Производительность скрипта CPU: Ryzen 5 2600 +--------------+---------+-------------+ | | pAttach | bone_attach | +--------------+---------+-------------+ | 10 objects | 1.5% | 2.8% | +--------------+---------+-------------+ | 50 objects | 6.5% | 13.3% | +--------------+---------+-------------+ | 500 objects | 61.2% | 114.3% | +--------------+---------+-------------+ | 1000 objects | 103.4% | 149.7% | +--------------+---------+-------------+
  3. Убедительно просим ознакомиться с данной темой перед публикацией своей заявки/резюме, в противном случае вы можете понести наказание от вынесения предупреждения до блокировки аккаунта. Заголовок новой темы должен быть оформлен по шаблону: Пример составления заголовка для заявки [Заявка] Заголовок Например: "[Заявка] Требуется скриптер для написания системы инвентаря" Пример составления заголовка для резюме [Резюме] Заголовок Например: "[Резюме] Скриптер, маппер" Заявка должна содержать в себе: - Описание работы - Грамотно составленное техническое задание - Дополнительные пожелания к ТЗ (если есть) - Сроки выполнения - Сумму вознаграждения - Дополнительные ссылки для связи (если есть) Резюме должно содержать в себе: - Виды выполняемых работ - Опыт работы в каждом виде - Портфолио (скриншоты, видео и т.д.) - Дополнительные ссылки для связи (если есть)
  4. На данный момент большинство имеющихся в сети LUA декомпиляторов умеют преобразовывать только простой код, чем более сложно устроен ваш скрипт, тем меньше вероятность его успешной декомпиляции. Как защитить исходники Скомпилируйте их максимально в 1 файл. Например: "Путь к компилятору\luac5.1.exe" -s -o "Путь\СкомпиленныйСкрипт123.lua" -- "Путь\Скрипт1.lua" "Путь\Скрипт2.lua" "Путь\Скрипт3.lua" Используйте максимально сложный по конструкции код. Например, локальные функции внутри других функций или определения функций в определении таблицы. Не оставляйте debug информацию в скомпилированном скрипте. Это, конечно, усложнит дебаг, но тем самым вы оставите меньше информации для чужих глаз. Чтобы отключить дебаг информацию, нужно компилировать скрипт с параметром "-s". Например: "Путь к компилятору\luac5.1.exe" -s -o "мой\Скрипт.luac" -- "мой\Скрипт.lua"  Также в случае возникновения ошибки дебаг укажет полный путь к исходнику скрипта. Еще один способ защиты - выложить код в массы как релиз или проект, закрыв в нем только важные компоненты, без которых он работать не будет. Изменяя открытый код, нужно менять и закрытый так, чтобы новая версия открытого кода могла работать только с новой версией закрытого. Тем самым кто-то сможет помочь вам доработать открытый код, если он будет популярен, но не сможет его полностью украсть и изменить.
  5. Автор статьи: Kernell В качестве примера, я буду использовать стандартный автомобиль Sultan, а перекрашивать я ему буду диски на колёсах. На самом деле данный метод будет работать на любых объектах игры, будь-то это объекты ландшафта или же персонажи. Но так как сегодня мы будем работать с ZModeler 2, то их рассматривать мы не будем (так как ZM2 не умеет работать с костями персонажей и плохо экспортирует обычные объекты). Сразу оговорюсь – имеется ввиду, что вы уже владеете основами работы с ZModeler 2, поэтому детально рассматривать эту программу мы не будем. К счастью русскоязычных уроков по ZM2 очень много. Подготовка И так, мы имеем проект с уже готовым автомобилем, который без проблем работает в нашей любимой игре. Теперь можно приступать к делу. Для того чтобы MTA смогла найти с каким материалом ей работать — мы должны передать ей имя с помощью engineApplyShaderToWorldTexture. При экспорте модели из ZModeler 2 все материалы принимают название первой текстуры в самом материале. Т.е. если ваша текстура называется WHEELS.tga – то материал будет называться WHEELS. Это очень важно, так как если вы просто покрасите колёса и не установите текстуру (хотя бы в 1px), то материал в игре будет называться unnamed, как и все у которых нет текстур. Реализация Так уж случилось, что диски моего автомобиля имеют текстуру vehiclegeneric256, которая не является уникальной (ею окрашены ещё другие части автомобиля) – это не редкое явление. Чтобы решить эту проблему, придётся создать копию этой текстуры и назвать так как нам нужно. Далее мы создаём новый материал, называем его как нам удобно (я предпочитаю чтобы имена материалов и имена текстур совпадали), добавляем новую текстуру, выделяем нужные нам полигоны и применяем к ним наш материал. Экспортируем нашу модель.. и а этом наша работа с ZModeler2 закончена. Пишем шейдер Сам по себе шейдер будет очень простой, мы создадим одну переменную которой мы сможем задавать значения цвета из скрипта, все остальные данные нам предоставит MTA. Для загрузки шейдера я использовал следующий скрипт (он очень простой, поэтому отдельно его рассматривать мы не будем): addEventHandler( "onClientResourceStart", resourceRoot, function() local shader = dxCreateShader( "color.fx" ); if shader then dxSetShaderValue( shader, "color", { 1.0, 0.5, 0.0 } ); engineApplyShaderToWorldTexture( shader, "wheels256" ); end end ); Теперь займёмся написанием самого шейдера. Объявляем переменные: float4 color = 1; sampler Sampler0 : register( s0 ); В качестве цвета мы используем переменную color - её значение мы будем устанавливать с помощью engineApplyShaderToWorldTexture Теперь нам необходимо взять текущий цвет пикселя и «смешать» его с нашим цветом (color): struct PSInput { float2 TexCoord : TEXCOORD0; }; float4 PixelShaderFunction( PSInput PS ) : COLOR0 { float4 texColor = tex2D( Sampler0, PS.TexCoord ); texColor *= color; return texColor; } Всё что и делает этот шейдер – просто перекрашивает пиксели текстуры. Как видно мы не учитываем освещение из-за чего наши колёса будут светиться в темноте как огни. И тут на помощь к нам приходит mta-helper.fx написанный нашими любимыми The MTA Team =) Так же они для нас написали замечательную функцию которая просчитывает дифьюзный цвет автомобиля с учётом глобального затенения мира – MTACalcGTAVehicleDiffuse. Функция первым аргументом требует нормали вершин. Так как пиксельный шейдер работает непосредственно с изображением, информацию о нормалях мы не имеем. Для этого нам придётся написать вершинный шейдер. Исправленный код шейдера: #include "mta-helper.fx" float4 color = 1; sampler Sampler0 : register( s0 ); struct VSInput { float4 Position : POSITION0; float3 Normal : NORMAL0; float4 Diffuse : COLOR0; float2 TexCoord : TEXCOORD0; }; struct PSInput { float4 Position : POSITION0; float2 TexCoord : TEXCOORD0; float4 Diffuse : COLOR0; }; PSInput VertexShaderFunction( VSInput VS ) { PSInput PS = (PSInput)0; float4 worldPosition = mul( VS.Position, gWorld ); float4 viewPosition = mul( worldPosition, gView ); float4 position = mul( viewPosition, gProjection ); PS.Position = position; PS.TexCoord = VS.TexCoord; PS.Diffuse = MTACalcGTAVehicleDiffuse( VS.Normal, VS.Diffuse ); return PS; } float4 PixelShaderFunction( PSInput PS ) : COLOR0 { float4 texColor = tex2D( Sampler0, PS.TexCoord ); texColor *= PS.Diffuse * color; return texColor; } technique { pass P0 { VertexShader = compile vs_2_0 VertexShaderFunction(); PixelShader = compile ps_2_0 PixelShaderFunction(); } } В вершинном шейдере мы создаем новый объект типа PSInput, который будет подаваться на вход в нашу функцию PixelShaderFunction. Так как объект изначально не имеет никаких данных, наша задача передать их, как мы и сделали это с TexCoord, Diffuse и Position. Так как основной задачей вершинного шейдера является установка вершин, то он должен определить семантику POSITION для выходного параметра. В нашем случае это Position. Чтобы получить правильную позицию вершины для пиксельного шейдера, мы умножаем её на мировую матрицу объекта (gWorld), затем на матрицу вида камеры (gView), а затем и на матрицу проекции камеры (gProjection). Далее всё просто, с помощью функции написанной разработчиками MTA мы просчитываем новый цвет и передаём в Diffuse. В пиксельном шейдере мы просто умножаем полученный Diffuse на наш color, вот собственно вот и всё. Пишем скрипт для шейдера Скрипт который я использовал выше не подходит для работы на реальном сервере, так как не поддерживает работу с несколькими объектами, ибо шейдер глобальный, а значит цвет колёс у всех машин будет один. Для этого нам нужно для каждого автомобиля создавать новый объект шейдера, который будет иметь своё значение цвета. Хранить информацию о цвете колёс мы будем в ElementData в виде таблицы – это позволит устанавливать цвет с серверной стороны (для этого мы будем отслеживать событие onClientElementDataChange). Так же мы будем отслеживать события onClientElementStreamIn, onClientElementStreamOut и onClientElementDestroy. Событие onClientElementStreamIn необходимо нам для того чтобы создать шейдер когда автомобиль попадёт в стример клиента, остальные два – для удаления шейдера. Скрипт шейдера: local vehicles = {}; function CreateVehicleShader( vehicle ) local color = getElementData( vehicle, "WheelsColor" ); if color then local shader = dxCreateShader( "color.fx" ); if shader then vehicles[ vehicle ] = shader; dxSetShaderValue( shader, "color", color ); engineApplyShaderToWorldTexture( shader, "wheels256", vehicle ); return true; end end return false; end function CheckVehicleShader( element ) local vehicle = element or source; if vehicle and getElementType( vehicle ) == "vehicle" then if vehicles[ vehicle ] then return true; end return CreateVehicleShader( vehicle ); end return false; end function DestroyVehicleShader( element ) local vehicle = element or source; if vehicles[ vehicle ] then destroyElement( vehicles[ vehicle ] ); vehicles[ vehicle ] = NULL; end end addEventHandler( "onClientElementStreamIn", root, CheckVehicleShader ); addEventHandler( "onClientElementStreamOut", root, DestroyVehicleShader ); addEventHandler( "onClientElementDestroy", root, DestroyVehicleShader ); addEventHandler( "onClientElementDataChange", root, function( key, oldValue ) if key == "WheelsColor" and getElementType( source ) == "vehicle" and CheckVehicleShader( source ) then dxSetShaderValue( vehicle[ source ], "color", getElementData( source, "WheelsColor" ) ); end end ); addEventHandler( "onClientResourceStart", resourceRoot, function() for i, vehicle in ipairs( getElementsByType( "vehicle", root, true ) ) do CheckVehicleShader( vehicle ); end end ); Как можно было заметить, функция CreateVehicleShader создаёт шейдер для нашего автомобиля. В случае успеха возвращает true. Вызов функции происходит только из CheckVehicleShader - она проверяет наличие шейдера для автомобиля, если его нет - создаёт его. В случае успеха так же возвращает true. Так как при старте ресурса в стримере уже могут быть автомобили и они могут иметь информацию о цвете (WheelsColor), мы используем событие onClientResourceStart для проверки всех автомобилей, что находятся в стримере. onClientElementDataChange мы отслеживаем на случай изменения информации о цвете со стороны сервера. Так как изначально её может не быть, то шейдер не будет создан при старте ресурса или когда автомобиль попадёт в стример игрока - для этого у нас есть функция CheckVehicleShader.
  6. Добавить сервер в мониторинг можно Здесь После добавления сервера необходимо скачать MonitoringAPI Поместите скачанный архив в папку mods/deathmatch/resources, затем откройте файл settings.lua находящийся в архиве, и впишите IP адрес (без порта) вашего сервера. Затем остановите сервер, и откройте файл acl.xml. Добавьте в группу Admin следующую строку: <object name="resource.MonitoringAPI"></object> И наконец откройте mtaserver.conf и добавьте в конец файла следующую строку: <resource src="MonitoringAPI" startup="1" protected="0" /> Сохраните изменения и запустите сервер. Поздравляю! настройка мониторинга на вашем сервере завершена!
  7. Сам ресурс: [Скачать ресурс] Поскольку этот ресурс синхронизирует трафик между игроками, на что затрачиваются достаточно значительные системные ресурсы, его необходимо тщательно настраивать, в противном случае возможны серьезные проблемы с производительностью или временные искажения текстур. Способ #1 Можно использовать предусмотренные команды ресурса - /density [тип_транспорта] плотность Минус этого способа в том, что параметры, примененные этой командой будут сброшены при перезапуске сервера. Способ #2 Если вы используете кастомный игровой режим вы можете вызвать функцию density с помощью экспорта: exports.npchlc_traffic:setTrafficDensity("peds",0.26) Примечание: т.к. игровой режим в большинстве случаев запускается раньше, чем успевает загрузиться ресурс трафика необходимо создать задержку выполнения этого кода. Для этого вполне подойдет таймер: setTimer ( function() exports.npchlc_traffic:setTrafficDensity("peds",0.26) exports.npchlc_traffic:setTrafficDensity("cars",0.21) end, 8700, 1 ) -- таймер сработает через 8.7 секунд после вызова Также вы можете встроить этот код в любой другой ресурс, запускаемый при старте сервера.

MTA Resource

MTA Resource — это свободнная площадка, на которой вы сможете обмениваться ресурсами, продавать ресурсы, просматривать видео уроки и туториалы по созданию собственных игровых режимов и скриптов, общаться и консультироваться на форумах и много всего прочего!

×
×
  • Create New...